Bug description
When the Claude Code CLI exits with code 1 and emits a result message where is_error=true but errors is an empty list (e.g. on a model_not_found 404), the SDK raises an exception with the message:
Claude Code returned an error result: success
The word "success" is the subtype field of the result JSON, used as a fallback label. It is not an error description — it just means the session terminated cleanly at the protocol level. The actual human-readable error sits in the result field of the same JSON object and is silently discarded.
Steps to reproduce
- Run the CLI with a non-existent model:
claude --output-format=stream-json --print --model nonexistent-model "hello"
Observe the last stdout line before exit 1:
{
"type": "result",
"subtype": "success",
"is_error": true,
"errors": [],
"result": "There's an issue with the selected model (nonexistent-model). It may not exist or you may not have access to it.",
"api_error_status": 404
}
- Use the SDK to invoke the same — the raised exception message will be
"Claude Code returned an error result: success" instead of the actual model error.
Root cause
query.py:304-307:
if message.get("is_error"):
errors = message.get("errors") or []
self._last_error_result_text = "; ".join(errors) or str(
message.get("subtype", "unknown error") # ← "success" when errors=[]
)
"; ".join([]) is "" (falsy), so it falls through to message.get("subtype"). For model_not_found and likely other API-level errors, subtype is "success" (indicating a clean protocol-level exit), producing the contradictory label.
The human-readable error is in message.get("result"), which is never consulted.
Expected behaviour
The exception should surface the actual error text:
Claude Code returned an error result: There's an issue with the selected model (nonexistent-model). It may not exist or you may not have access to it.
Suggested fix
if message.get("is_error"):
errors = message.get("errors") or []
self._last_error_result_text = (
"; ".join(errors)
or message.get("result") # ← check result field before subtype
or str(message.get("subtype", "unknown error"))
)
Version
claude-agent-sdk==0.2.97
- Observed via
claude-code v2.1.173 with --output-format=stream-json
Bug description
When the Claude Code CLI exits with code 1 and emits a
resultmessage whereis_error=truebuterrorsis an empty list (e.g. on amodel_not_found404), the SDK raises an exception with the message:The word
"success"is thesubtypefield of the result JSON, used as a fallback label. It is not an error description — it just means the session terminated cleanly at the protocol level. The actual human-readable error sits in theresultfield of the same JSON object and is silently discarded.Steps to reproduce
claude --output-format=stream-json --print --model nonexistent-model "hello"Observe the last stdout line before exit 1:
{ "type": "result", "subtype": "success", "is_error": true, "errors": [], "result": "There's an issue with the selected model (nonexistent-model). It may not exist or you may not have access to it.", "api_error_status": 404 }"Claude Code returned an error result: success"instead of the actual model error.Root cause
query.py:304-307:"; ".join([])is""(falsy), so it falls through tomessage.get("subtype"). Formodel_not_foundand likely other API-level errors,subtypeis"success"(indicating a clean protocol-level exit), producing the contradictory label.The human-readable error is in
message.get("result"), which is never consulted.Expected behaviour
The exception should surface the actual error text:
Suggested fix
Version
claude-agent-sdk==0.2.97claude-code v2.1.173with--output-format=stream-json