You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
The batch commands disagree about exit status, and upload --json emits two documents #27
The three batch commands disagree with each other about exit status, and one of them emits a --json stream that cannot be parsed. Three related defects:
1. assets edit exits 0 when every edit was rejected. It prints Edited 0 photographs. and
returns Ok(()). upload and download both bail! in the equivalent case. A script that
submits 100 edits and has all 100 refused by the server sees success.
This one directly undercuts #23: that issue made the rejection say which field was wrong, but
a caller checking $? still never learns anything was wrong at all.
2. upload --json emits two JSON documents when a file fails.ctx.out.json(...)? writes the
result, then bail! sends main::report to write {"error":"N files failed",…} to the same
stdout. The stream is then two concatenated documents, which breaks jq and any ordinary parser. src/output.rs states the contract this contradicts.
3. download --json exits 0 while the identical run in prose exits 1. Its JSON branch returns
before the bail!. The mirror image of (1) — and it means the same failure reports differently
depending on which audience asked.
Reproduction
imogen assets edit <id> <id> --taken-at <value the server refuses>; check $? — 0.
imogen upload <dir> --json with one file the server rejects; pipe to jq — parse error on
trailing content.
imogen download <selection> --json where a file fails; check $? — 0. Run the same without --json; $? is 1.
Expected
One rule, applied by all three: a batch in which every item failed exits non-zero; a partial
failure exits with whatever the commands agree on (and they should agree); and --json emits exactly one document on stdout whatever happens, with the failure represented inside it
rather than appended after it.
Worth settling the partial-failure case deliberately rather than per-command, since that is how
the three drifted apart.
Affected repos
Only this one. Nothing on the wire changes.
Context
Found by review while implementing #23 and #24, both of which were about the content of a
failure report. This is about its exit status and framing, which is the half a script actually
depends on. Pre-existing in all three commands.
The rule the three now share, from finish_batch in src/commands/mod.rs:
0 when nothing was refused, 1 when nothing got through, 3 when some items succeeded and some were refused. 2 is left to clap's usage error, so a script can tell "you called me wrong" from "some of it failed". The partial case earns its own code because "the server is down, nothing landed" and "ninety-seven landed, three were refused" call for different things — stopping and shouting versus reading failures and retrying those three.
--json puts exactly one document on stdout. A failing batch writes nothing there itself: the summary travels out with BatchFailure and main::report writes it once, with the sentence added under error.
A run that got nothing through no longer closes with a green line claiming it did.
Behaviour change for scripts, noted in the PR body: an all-refused edit and a failing download --json now exit non-zero where they exited 0, and a partial upload/download exits 3 where it exited 1.
Tests are in tests/batch_exit_status.rs, run against a stub server so $? and the stdout bytes are the real ones; the single-document property is asserted by parsing the whole stream and counting.
The album-fill failure a few lines above the new finish_batch call is still ctx.out.warn(...) and still exits 0 — that is #34's second half, left where it is.
Activity
ergofobe commentedon Sep 16, 2026
Fixed in #39, merged as 455d52c.
The rule the three now share, from
finish_batchinsrc/commands/mod.rs:failuresand retrying those three.--jsonputs exactly one document on stdout. A failing batch writes nothing there itself: the summary travels out withBatchFailureandmain::reportwrites it once, with the sentence added undererror.Behaviour change for scripts, noted in the PR body: an all-refused
editand a failingdownload --jsonnow exit non-zero where they exited 0, and a partialupload/downloadexits 3 where it exited 1.Tests are in
tests/batch_exit_status.rs, run against a stub server so$?and the stdout bytes are the real ones; the single-document property is asserted by parsing the whole stream and counting.The album-fill failure a few lines above the new
finish_batchcall is stillctx.out.warn(...)and still exits 0 — that is #34's second half, left where it is.Count the fills that worked, and say what for_id is for now