Repository navigation
Conversation
…erminal The notice is advice for a person. A program that runs eas-cli reads stderr for the command's error and found this notice first. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
vonovak
force-pushed
the
vonovak/json-error-output
branch
from
October 9, 2026 19:04
829bf1c to
3da5c85
Compare
This was referenced Oct 9, 2026
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## vonovak/failure-reason-stderr #4593 +/- ##
=================================================================
+ Coverage 74.04% 74.06% +0.02%
=================================================================
Files 1018 1018
Lines 49544 49569 +25
Branches 10684 10690 +6
=================================================================
+ Hits 36680 36707 +27
+ Misses 11871 11869 -2
Partials 993 993 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
vonovak
force-pushed
the
vonovak/json-error-output
branch
from
October 9, 2026 19:42
3da5c85 to
d466904
Compare
vonovak
added this pull request to stack #4595
October 9, 2026 19:52
EasCommand.catch printed the reason with Log.error, which writes to stdout. oclif then printed "<command> command failed." to stderr. A program that reads stderr for the error found only that generic line. Only the catch changes. Other Log.error and Log.warn calls stay on stdout, because some of them are not failures and the spinner keeps non-TTY output off stderr on purpose. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A command run with --json printed nothing on stdout when it failed, so
a program had to read the human message.
- EasCommand.run enables JSON output before the context is resolved,
so context messages and errors stay off stdout. build:list enabled it
only after getContextAsync.
- EasCommand.catch prints {"error": {"message", "requestId"?}}. The
request ID is the one the human message already shows. Once per
process, because update:rollback runs other commands in-process.
- Errors.exit(1) carries no reason, so its message is
"<command> command failed." instead of "EEXIT: 1".
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
vonovak
force-pushed
the
vonovak/json-error-output
branch
from
October 12, 2026 08:04
d466904 to
1dcfc9a
Compare
|
✅ Thank you for adding the changelog entry! |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Why
When a command run with
--jsonfails, stdout holds no JSON. A program must read the human message. Also,build:listenables JSON output only aftergetContextAsync, so errors from the context step went to stdout as text.Stacked on #4592. This is the third of four PRs: #4591 ← #4592 ← #4593 (this PR) ← #4594. Error codes are not in this PR. #4594 adds them, so the eas-cli team can decide on that contract separately.
How
EasCommand.runenables JSON output beforerunAsyncwhen the command declares ajsonflag and--jsonis in argv. The check copies oclif'sjsonEnabled, so--jsonafter--does not count.enableJsonOutputdoes nothing on a second call, so the existing calls in commands stay correct.EasCommand.catchprints this object on stdout:{ "error": { "message": "...", "requestId": "..." } }requestIdcomes from the first GraphQL error. The human message already shows it. The message has no ANSI codes. GraphQL error codes are not printed, because they belong to the server.The error prints once per process.
update:rollbackrunsupdate:republishin the same process, and the innermost error is the one that says what went wrong.Errors.exit(1)carries no reason, so its JSON message is<command> command failed.instead ofEEXIT: 1. The reason is on stderr.Known limits:
process.exitcalls do not reachcatch, so they print no JSON error. A follow-up can turn them into throws.metadata:lint --jsonprinted nothing on stdout when it failed for a reason other than validation. It now prints the error object.LLM Authorship
--json. Claude Code wrote the change.enableJsonOutputcall and the once-per-process rule forupdate:rollback. An AI diff review checked every command with ajsonflag: each enables JSON output only under that flag, and none writes its result withLog.log. The same review found theEEXITmessage, which is now fixed and tested.Test Plan
EasCommandtests: JSON output is on beforerunAsync; the JSON error for anEasCommandError, forErrors.exit, and for a GraphQL error (request ID, no server code); no JSON error without--json, with--jsonafter--, or for a command without ajsonflag.json-test.ts: one object on stdout, without ANSI codes, once per process.Real run, not logged in,
build:list --json --non-interactivein a project witheas-cliindevDependencies:24.12.1 printed the reason as text on stdout, and the dependency notice first on stderr.
config --json --profile x: stdout is{"error": {"message": "Missing build profile in eas.json: \"x\". Available profiles: []"}}.eas-cli unit tests: 3253 passed. 2 tests in
simulator/__tests__/egressLimits.test.tsfail withECONNRESETon localhost. They fail the same way onmainon this machine.tsc,oxlintandoxfmtare clean.🤖 Generated with Claude Code