Relationships
#2938 --json stderr mixes an offline auth-gate warning line with the pretty-printed error, so it can't be parsed
Opened by stack72 · 10/2/2026· Shipped 10/2/2026
Summary
Since #2786 ("honest offline warning when the fail-open window can't be recorded", swamp-club#2916), a --json command that passes the auth gate as offline and then fails writes two JSON documents in mixed formats to stderr: first a compact, single-line warning, then the pretty-printed, multi-line error. Stderr can no longer be parsed as one JSON document, and it isn't valid NDJSON either, so --json consumers can't reliably read the error.
Reproduction
Use a collective key and signin token (as in CI) and make swamp-club unreachable:
HOME=$(mktemp -d) \
SWAMP_API_KEY=[REDACTED-SECRET-1] SWAMP_SIGNIN_TOKEN=[REDACTED-SECRET-1] \
HTTPS_PROXY=http://127.0.0.1:1 HTTP_PROXY=http://127.0.0.1:1 \
swamp source fetch --json --version mainStderr:
{"warning":"Running offline (could not reach swamp-club.com); using your cached verification.","authMode":"offline"}
{
"error": "Download failed: ...",
...
}JSON.parse(stderr) fails with Unexpected non-whitespace character after JSON at position 117 (line 2 column 1). Position 117 is the end of the warning line.
Expected
In --json mode, a failing command's stderr is a single parseable JSON error document, as it was before #2786. The UAT test swamp source fetch fails with error when network is unreachable (swamp-uat tests/cli/source/fetch_test.ts) asserts this, and 17 UAT test files rely on the same contract.
Regression window
- Last good:
20261002.000056.0-sha.a1e4cae5 - First bad:
20261002.002942.0-sha.ef563473(only commit in the range: #2786) - Fails deterministically on every UAT run since then, e.g. https://github.com/swamp-club/swamp-uat/actions/runs/36950432687
Cause
src/cli/mod.ts now calls renderAuthGateWarning(outputMode, gateOutcome.warning). In JSON mode, src/presentation/renderers/auth_gate_warning.ts writes JSON.stringify({ warning, authMode: "offline" }) to stderr with console.error. Errors in JSON mode are still pretty-printed to stderr afterwards, so the stream mixes formats. design/surfaces/auth-gate.md documents the extra line but doesn't account for how it combines with the JSON error output.
Suggested fix
One of these:
- Carry the warning on the command's own JSON output instead of as a separate document, e.g.
warning/authModefields on the error object (and the success payload), or - If it stays a separate line, emit JSON-mode errors as single-line JSON so stderr is valid NDJSON, and document that stderr in
--jsonmode is NDJSON.
Shipped
Click a lifecycle step above to view its details.
Sign in to post a ripple.