Repository navigation
Description
Summary
Three output-handling defects that together make --output json unsafe to script against. Found while exercising a v2.6.0 release-candidate build; all three look pre-existing and CLI-wide rather than introduced by the 2026-09-01 work.
1. Errors print to stdout, not stderr
Exit codes are correct throughout, but the error text lands on stdout, so a pipeline gets non-JSON where it expects JSON:
hookdeck gateway metrics events --start ... --end ... --output json 2>/dev/null
# → query event metrics: error: unexpected http status code: 422 {...} [on STDOUT, exit 1]
hookdeck gateway attempt list --output json 2>/dev/null
# → --event-id is required [on STDOUT, exit 1]
hookdeck project list 2>/dev/null
# → this credential is scoped to a single project... [on STDOUT, exit 1]cmd --output json | jq therefore fails on a parse error rather than on the exit code. API errors are additionally duplicated to stderr by the logger; client-side errors appear on stdout only.
In a sweep of every read command, gateway attempt list was the only one whose stdout failed to parse as JSON, and this was the reason — not malformed JSON.
2. --output silently ignores unrecognised values
hookdeck gateway metrics events ... --output JSON # capitalised
hookdeck gateway metrics events ... --output yaml
hookdeck gateway metrics events ... --output ""All three print the human-readable table, exit 0, no warning. A script passing --output JSON gets unparseable text and no signal that anything was wrong.
Note the inconsistency with a neighbouring flag: project list --type validates case-sensitively with a clear error naming the valid set, while --output validates case-sensitively silently.
3. whoami has no JSON output
hookdeck whoami --output json
# → unknown flag: --output [exit 1]Every gateway and project read command supports --output json; whoami does not, so a script cannot read the current project or organization without parsing the table. Its table output also renders an empty parenthetical for the email: Logged in as macdeck () on project ....
Suggested direction
- Route all error output through stderr.
- Reject unknown
--outputvalues with a message naming the valid set, matching what--typealready does. - Add
--output jsontowhoami.
(1) and (2) are behaviour changes for anyone currently capturing errors from stdout, so they may warrant a minor version rather than a patch.
Verified working, for contrast
Valid JSON on stdout with clean stderr for metrics events/requests/attempts/transformations, source list, connection list, destination list, event list, issue list, request list, transformation list. Empty result sets correctly emit []. No stray log lines on stdout on the success path at default log level.
Filed by Claude on Phil's behalf, from release-candidate testing.
Activity
leggetter commentedon Sep 14, 2026
Partial overlap with #367, flagged for triage rather than closed.
#367 ("CLI output and error-reporting papercuts") already covers one of the three items here:
That is the same defect as item 2 in this issue, found independently against a different command. #367 also covers adjacent output problems — raw transport log noise,
countlacking--output json— so whoever picks either up should read both.The other two items here are not in #367 and are the more consequential ones:
cmd --output json | jqreceives an English sentence on the JSON channel. Since confirmed acrossgateway metrics,gateway attempt list,project list,project useandlogin --cli-key, with correct exit codes throughout. Note the convention is inconsistent within the same release:listen's--output interactivefallback warning correctly goes to stderr.whoamihas no--output json, so a script cannot read the active project without parsing a table.Suggest either folding item 2 into #367 and keeping this for the stdout/stderr work, or closing #367's
--outputbullet in favour of this one — but not fixing both independently.(Housekeeping by Claude, on Phil's behalf.)
fix(transformation): keep --output json parseable when a run fails
leggetter commentedon Sep 15, 2026
Concrete instance, and a partial fix landing in v2.6.0 that is worth recording here so the remaining gap is visible.
Fixed in 2.6.0, narrowly. #417 made
gateway transformation runreport a failed run as a failure. The first version of that fix returned the reason as an ordinary error, which Execute prints to stdout — so--output jsonemitted the payload followed by a prose line and the stream stopped parsing:That is now fixed: the reason goes to stderr, stdout stays pure JSON, and the exit code carries the failure. Verified — stdout 175 bytes of valid JSON, stderr 36 bytes, exit 1.
It needed a new
alreadyReportedErrortype inpkg/cmd/root.go: Execute exits on it without printing, so a command producing machine-readable output can fail without writing prose to stdout. Onlytransformation runuses it so far.Still broken on the same command. When the request fails rather than the transformation — network error, 401, 500 — the error returns earlier and still goes to stdout:
So
--output jsonis parseable when the transformation fails, and not parseable when the API call fails. Same command, two failure modes, two behaviours.I deliberately did not extend the fix to that branch during the release: the same argument applies to every
--output jsoncommand in the CLI, and doing it properly is this issue rather than a patch on one command.Suggested shape when this is picked up:
alreadyReportedErroralready exists as the mechanism. Either route every error through it when--outputis set, or — cleaner — change Execute's default branch to print to stderr unconditionally, which is what this issue proposes. Note the second is a behaviour change for anyone currently capturing errors from stdout, so it may belong in a major.(Noted by Claude on Phil's behalf, from v2.6.0 release testing.)
!20268 merge bump-hookdeck-2.6.0 into main