qwen-code/packages/cli
Umut Polat a08d48b75c
fix(cli): stop double-wrapping and double-printing API errors in non-interactive mode (#3749)
* fix(cli): stop double-wrapping and double-printing API errors in non-interactive mode

In non-interactive (-p) mode, any upstream 4xx ended up on stderr three
times: once from the stream-error handler, once from handleError after
the thrown Error.message (already containing the formatted text) was
fed back through parseAndFormatApiError producing
"[API Error: [API Error: ...]]", and once more from
JsonOutputAdapter.emitResult writing the same errorMessage out in TEXT
mode. The top-level catch then framed the resulting throw as
"An unexpected critical error occurred:" with a stack trace, which
made a routine 4xx look like a CLI crash.

Three coordinated changes:

- AlreadyReportedError marks a throw whose message is already on the
  wire. handleError short-circuits on it: no second writeStderrLine,
  no second parseAndFormatApiError, just propagate the exit code.
- The non-interactive stream-error handler now throws
  AlreadyReportedError, and the catch block skips the adapter's
  emitResult in TEXT mode so we don't get a third copy.
- The top-level .catch in packages/cli/index.ts treats
  AlreadyReportedError as a routine, already-reported failure: exit
  with the carried code without printing the "unexpected critical"
  framing or the stack trace.

parseAndFormatApiError is also made idempotent — input that already
starts with "[API Error: " and ends with "]" is returned unchanged.
That is the safety net: even if a future caller forgets to mark its
throw, the double-wrap symptom is impossible.

Tests cover all three layers: idempotency in errorParsing, the
short-circuit in handleError, and a regression test on
runNonInteractive that asserts no "[API Error: [API Error: ...]" line
is ever produced on stderr.

Fixes #3748

* fix(cli): make API error formatting idempotent for 429 suffix + use AlreadyReportedError

* fix(cli): follow up on error reporting review
2026-05-03 08:39:31 +08:00
..
src fix(cli): stop double-wrapping and double-printing API errors in non-interactive mode (#3749) 2026-05-03 08:39:31 +08:00
index.ts fix(cli): stop double-wrapping and double-printing API errors in non-interactive mode (#3749) 2026-05-03 08:39:31 +08:00
package.json chore(release): v0.15.6 (#3766) 2026-04-30 15:59:35 +08:00
test-setup.ts fix: prevent bogus shell permission rules in tests 2026-03-20 17:55:33 +08:00
tsconfig.json Add background agent resume and continuation (#3739) 2026-05-01 12:14:33 +08:00
vitest.config.ts refactor(core): Unify package exports and improve dev experience 2026-02-01 11:59:05 +08:00