Skip to content

Write a JSON error object to stdout when a command fails under --output json - #71

Merged
cretz merged 4 commits into
mainfrom
cretz/json-error-output
Sep 10, 2026
Merged

cretz merged 4 commits into
mainfrom
cretz/json-error-output

Conversation

@cretz

@cretz cretz commented Sep 2, 2026

Copy link
Copy Markdown
Collaborator

🚀 What

  • Failed commands under --output json/jsonl now write a structured error to stdout, not just a message to stderr (fixes Provide error JSON object with message for JSON output on errors #68)
  • Shape: {"error": {"message", "type", "exit_code", "api_status_code"?, "api_error_code"?, "api_details"?}}, the api_* fields only for failed API calls
  • Interrupts get a real ErrInterrupted type, so exit code 130 is now listed in --help-output
  • Bad flags and unknown subcommands now exit 2 (ExitUsage) instead of 1, and get an envelope too
  • Usage text on error moves from stdout to stderr

💻 How

  • cmd.JSONErrorEnvelope/JSONError in the public package, rendered as a schema in baseten --help-output
  • apiErrorFields pulls status, code, and details off the management/inference client errors already in the chain, best-effort: unparseable bodies contribute only the status
  • message is the error chain verbatim, so an API failure still carries the raw response body
  • ctx.SuppressJSONError() for commands whose payload already reports the failure (model push --wait), keeping stdout one document under --output json. Subprocess passthrough (truss) writes no envelope either
  • Pre-parse failures never reach a runner, so Execute classifies them and reads --output straight from argv
  • Usage now renders via c.UsageString() to stderr; cobra's Usage() writes to the SetOut writer, which is stdout here

🔬 Testing

  • New internal/cmd/errors_test.go: management error with code and details, proxy 401 with neither, non-JSON 502, local failure, text mode, jsonl single line, --jq bypass, unknown flag, unknown subcommand, bad --output value, interrupt, help docs
  • Updated the model-push and deployment-logs tests for the new stdout shapes

@cretz
cretz requested review from marius-baseten and a lite review from Copilot September 2, 2026 19:59

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

There are a few correctness gaps in the new logic/tests (inference API detail not mapped into api_details, -q<expr> shorthand not detected for pre-parse JSON classification, and a test helper’s single-document assertion is unreliable) that should be fixed before merging.

Once you've addressed the issues Copilot identified, you can request another Copilot review.

Pull request overview

This PR extends the CLI’s JSON/JSONL output contract so that failures also emit a structured cmd.JSONErrorEnvelope to stdout (as the final JSON document), while continuing to print the plain-text error message (and usage, when applicable) to stderr. It also introduces a dedicated ErrInterrupted type and updates help/docs and tests to reflect the new behavior.

Changes:

  • Add public cmd.JSONErrorEnvelope / cmd.JSONError types and document them in --help-output.
  • Emit JSON error envelopes on command failures under --output json/jsonl, including for cobra pre-parse failures and interrupts; allow commands to suppress the envelope when their payload already reports failure.
  • Add/adjust tests for envelope emission behavior across API/local/usage/subcommand/interrupt cases and streamed jsonl commands.
File summaries
File Description
internal/help/output.go Documents JSON error envelope behavior and renders schema codeblocks for help output.
internal/cmd/errors.go Extracts api_* fields from HTTP client errors to populate the JSON error envelope.
internal/cmd/errors_test.go New tests validating error envelope shape and stdout/stderr behavior across failure modes.
internal/cmd/command.model_push.go Suppresses the envelope when model push payload already encodes the failure.
internal/cmd/command.model_push_test.go Updates tests to reflect suppressed/enveloped JSON stdout behavior.
internal/cmd/command.model_deployment_logs_test.go Updates streamed jsonl failure test to account for appended error envelope.
internal/cmd/command.go Emits JSON envelopes for leaf failures; classifies cobra pre-parse failures as usage and envelopes them; moves usage output to stderr.
internal/cmd/command_context.go Adds SuppressJSONError and centralized envelope emission (writeJSONError).
CONTRIBUTING.md Documents the new JSON error envelope behavior and suppression hook.
cmd/errors.go Adds ErrInterrupted, ErrorTypeName, and public JSON error envelope types.
Review details
  • Files reviewed: 10/10 changed files
  • Comments generated: 3
  • Review effort level: Lite

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread internal/cmd/command.go Outdated
Comment thread internal/cmd/errors.go
Comment thread internal/cmd/errors_test.go
@cretz
cretz merged commit 369dcda into main Sep 10, 2026
4 checks passed
@cretz
cretz deleted the cretz/json-error-output branch September 10, 2026 16:23
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Provide error JSON object with message for JSON output on errors

3 participants