Skip to content

fix(cli): JSON error envelope on parse failure under --format json (#500)#535

Open
avrabe wants to merge 1 commit into
mainfrom
fix/500-json-parse-error-envelope
Open

fix(cli): JSON error envelope on parse failure under --format json (#500)#535
avrabe wants to merge 1 commit into
mainfrom
fix/500-json-parse-error-envelope

Conversation

@avrabe

@avrabe avrabe commented Jun 14, 2026

Copy link
Copy Markdown
Contributor

What

rivet's top-level --project / --schemas are not clap global args, so they only parse before the subcommand:

  • rivet --project X validate
  • rivet validate --project X → clap parse error

clap writes that error to stderr and leaves stdout empty, so a --format json consumer (e.g. the subprocess in #488) got an empty payload and a cryptic EOF while parsing a value, with no hint that the arg position was the cause.

Why not global = true

The issue suggests global = true, but that's a known trap in this repo: global debug-asserts against positional subcommands and broke main once (REQ-209 / #501, reverted in #502). So this takes the safe, additive route instead.

How

Parse via Cli::try_parse(); on error, when argv requested JSON (--format json / -f json, all spellings), print a one-line envelope on stdout:

{"error":"unexpected argument '--project' found","hint":"rivet's top-level options are not positional-global: pass --project/--schemas BEFORE the subcommand, e.g. `rivet --project <dir> <subcommand>`"}

…then still emit clap's normal human message to stderr and exit with clap's code. --help/--version pass through (exit 0); non-JSON parse errors keep the stderr-only behavior (empty stdout, unchanged).

Tests

New json_consumers_get_an_error_envelope_on_parse_failure: misplaced --project --format json → valid JSON envelope on stdout with error+hint (exit ≠ 0); the same without JSON → empty stdout. cargo test -p rivet-cli --test cli_commands 132 pass; clippy --all-targets -D warnings + fmt clean.

Closes #500. Implements REQ-219.

🤖 Generated with Claude Code

@github-actions github-actions Bot 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.

⚠️ Performance Alert ⚠️

Possible performance regression was detected for benchmark 'Rivet Criterion Benchmarks'.
Benchmark result of this commit is worse than the previous benchmark result exceeding threshold 1.20.

Benchmark suite Current: f0c316e Previous: 6b160cf Ratio
traceability_matrix/1000 58825 ns/iter (± 230) 45348 ns/iter (± 269) 1.30
query/10000 330478 ns/iter (± 1877) 232848 ns/iter (± 5826) 1.42

This comment was automatically generated by workflow using github-action-benchmark.

@github-actions

github-actions Bot commented Jun 14, 2026

Copy link
Copy Markdown

📐 Rivet artifact delta

Change Count
Added 1
Removed 0
Modified 0
Downstream impacted (depth ≤ 5) 0

Graph

graph LR
  REQ_219["REQ-219"]:::added
  classDef added fill:#d4edda,stroke:#28a745,color:#155724
  classDef removed fill:#f8d7da,stroke:#dc3545,color:#721c24
  classDef modified fill:#fff3cd,stroke:#ffc107,color:#856404
  classDef overflow fill:#e2e3e5,stroke:#6c757d,color:#495057,stroke-dasharray: 3 3
Loading
Added
  • REQ-219

📎 Full HTML dashboard attached as workflow artifact rivet-delta-pr-535download from the workflow run.

Posted by rivet-delta workflow. The graph shows only changed artifacts; open the HTML dashboard (above) for full context.

@codecov

codecov Bot commented Jun 14, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

…json (REQ-219, #500)

rivet's top-level `--project`/`--schemas` are not clap `global` args, so they
parse only before the subcommand. `rivet validate --project X` is a parse error;
clap writes it to stderr and leaves stdout empty, so a `--format json` consumer
(e.g. a subprocess from #488) got an empty payload and a cryptic "EOF while
parsing a value" with no hint about the arg position. The obvious `global = true`
fix is a known trap — it debug-asserts against positional subcommands and broke
main once (REQ-209/#501, reverted #502).

Fix (no `global`): parse via `Cli::try_parse()`; on error, when argv requested
JSON (`--format json`/`-f json`, any spelling), print a one-line
`{ "error", "hint" }` envelope on stdout (hint: pass --project/--schemas BEFORE
the subcommand), then still emit clap's human message to stderr and exit with
clap's code. `--help`/`--version` pass through (exit 0); non-JSON parse errors
keep the stderr-only behavior (empty stdout).

Confirmed with the new `json_consumers_get_an_error_envelope_on_parse_failure`
integration test and `cargo test -p rivet-cli --test cli_commands` (132 pass);
`cargo fmt --check` + `cargo clippy --all-targets -- -D warnings` clean;
`rivet validate` PASS.

Implements: REQ-219
Refs: REQ-007
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@avrabe avrabe force-pushed the fix/500-json-parse-error-envelope branch from f0c316e to 7b2e84b Compare June 14, 2026 12:17
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.

Top-level args (--project / --schemas) aren't globalrivet validate --project X errors instead of working in any position

1 participant