Relationships
#851 autoGc emits auto_gc_completed event on --json stdout, breaking single-parse consumers
Opened by mgreten · 6/27/2026· Shipped 6/28/2026
First — thank you for shipping auto-GC (#823), it's exactly the inline-cleanup mechanism I'd hoped for. I hit one side effect worth flagging.
What happens
With autoGc: true enabled, swamp model method run <model> <method> --json emits a second JSON object on stdout after the result: the method's result object (pretty-printed), immediately followed by a line like:
{"event":"auto_gc_completed","versionsDeleted":2,"bytesReclaimed":7508}So the --json stdout is now two concatenated JSON values. Any consumer that does a single parse of the output breaks:
python3 -c "import sys,json; json.load(sys.stdin)"→json.decoder.JSONDecodeError: Extra data: line N column 1- Ruby
JSON.parse(stdout)→ raises on the trailing object.
In my case this broke several poller bridge scripts and an internal Ruby shellout helper that all consume --json with a single parse — they'd worked fine until autoGc was enabled, then started failing on every run that triggered a collection. Disabling autoGc immediately restored clean single-object --json output and everything parsed again.
Why it's worth fixing
The whole point of --json is machine-readable, single-document output for piping into a parser. An auto-GC lifecycle event appended to that stream means --json is no longer reliably parseable by the most common consumer pattern (one parse of stdout). It also means enabling autoGc silently changes the output contract of every method run for every downstream tool.
A few directions that could work
- Keep the
auto_gc_completedevent off stdout under--json— emit it to stderr, or to the log stream, or fold it into the single result object (e.g. agc:field on the existing result) rather than as a second top-level document. - Or gate the event line behind a verbose/non-json mode so
--jsonstays single-document.
Whichever fits — the key property is that --json stdout stays exactly one JSON value regardless of whether auto-GC fired.
Repro
- Set
autoGc: truein.swamp.yamlon an@swamp/s3-datastorerepo with some collectable (expired/excess-version) data. swamp model method run <model> <method> --json | python3 -c "import sys,json;json.load(sys.stdin)"- On a run where auto-GC collects something →
JSONDecodeError: Extra data. DisablingautoGc→ clean parse.
Environment
@swamp/s3-datastore@2026.06.26.1- swamp
20260626.202321.0
Thanks again — happy to share fuller sample output if useful.
Shipped
Click a lifecycle step above to view its details.
mgreten commented 6/27/2026, 2:17:45 AM
Wow... Claude got a little snarky in that stuff above. Super thankful for everything you all do!
mgreten commented 6/29/2026, 1:59:35 PM
Confirmed fixed on swamp 20260629.120229.0 — thank you for the quick turnaround!
I verified it both in an isolated repo and against our live shared MinIO datastore: with autoGc: true and collectable data present, a swamp model method run … --json now emits exactly one JSON object on stdout, the auto_gc_completed event no longer appears on the stream, and collection still fires (versions got trimmed to the cap on disk). Our single-parse poller bridges and the Ruby shellout helper parse cleanly again.
We've re-enabled autoGc: true on our high-churn namespaces — it's a great fit for keeping the index from accreting. Really appreciate the work on this one.
Sign in to post a ripple.