062096b20d
Secret scan / Scan diff for credential-shaped strings (pull_request) Successful in 21s
CI / Adapter unit tests (pull_request) Successful in 1m38s
CI / Adapter unit tests (push) Successful in 1m46s
CI / validate (pull_request) Successful in 7m0s
CI / validate (push) Successful in 7m3s
When the `claude` CLI errors mid-stream, claude-agent-sdk throws a bare
`Exception("Command failed with exit code 1 …")` whose only text is the
useless `Check stderr output for details` placeholder — but the *actual*
failure reason (model 404, rate limit, auth) arrived a moment earlier as a
stream-json `ResultMessage(is_error=True)` carrying `result` text and
`api_error_status`. That was thrown away.
`_run_query` now captures `ResultMessage(is_error=True)` detail (and, as a
fallback, the trailing AssistantMessage text) and re-attaches it to the
raised exception as `_molecule_stream_detail`. `_format_process_error`
surfaces it as `cli_stream_error=…` and, when present, skips the
`_probe_claude_cli_error` re-probe (#160) — the probe can't replay the
failing `--model`/`--system-prompt` argv, so it may even succeed and
mislead. The probe stays as the last resort when there's nothing to salvage.
Regression context: the 2026-05-10 dev-team incident — six lead workspaces
404ing on every turn (`--model claude-code` → `api_error_status=404`,
"There's an issue with the selected model (claude-code)"), invisible for an
hour because the CLI wrote nothing to stderr and this text was discarded.
See internal#226 follow-up #5.
Tests: tests/test_executor_error_detail.py — 6 cases (format surfaces the
salvaged detail; format still probes when there's nothing salvaged; salvaged
detail takes precedence over the probe; _run_query annotates from
ResultMessage(is_error); _run_query falls back to assistant text; clean
success path unaffected). `pytest tests/` → 87 passed.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>