Include x-should-retry signal in structured result event output
Summary
When the Anthropic API returns HTTP 500 with x-should-retry: false, Claude CLI emits a structured result event like:
{
"type": "result",
"subtype": "success",
"is_error": true,
"result": "API Error: 500 {\"type\":\"error\",\"error\":{\"type\":\"api_error\",\"message\":\"Internal server error\"},\"request_id\":\"req_011CZ9DRTWaz2QXRwFPE5vig\"}",
"num_turns": 219,
"session_id": "672be36f-1ddf-4d71-8639-66b662fd79c0",
"total_cost_usd": 13.58
}
This event does not include whether the error was marked retryable by the server (x-should-retry header). The header is only visible in the debug log output (ANTHROPIC_LOG=debug), not in the structured JSON stream.
Problem
Outer wrappers that run claude --output-format stream-json (like automated CI/CD systems, agent orchestrators, etc.) receive the structured events but cannot make informed retry decisions without parsing unstructured debug text.
In a real incident (session 672be36f-1ddf-4d71-8639-66b662fd79c0), a wrapper retried a 500 error 4 times with exponential backoff (wasting ~18 minutes), even though the API had explicitly set x-should-retry: false on every single response. The wrapper had no way to know this from the structured output.
Reproducible Example
Run claude with --output-format stream-json. When a 500 error occurs with x-should-retry: false:
Actual structured output (no retry signal):
{"type":"result","is_error":true,"result":"API Error: 500 {...}","session_id":"..."}
What debug log shows (not accessible to outer wrappers):
[log_42f85c] response error (error; not retryable) {
status: 500,
'x-should-retry': 'false'
}
Proposed Solution
Include the retry signal in the result event:
{
"type": "result",
"is_error": true,
"result": "API Error: 500 ...",
"should_retry": false,
"session_id": "..."
}
Or alternatively, include the HTTP status and headers in the error output so callers can make their own decisions:
{
"type": "result",
"is_error": true,
"result": "API Error: 500 ...",
"api_error": {
"status": 500,
"should_retry": false,
"request_id": "req_011CZ9DRTWaz2QXRwFPE5vig"
}
}
Workaround
Until this is fixed, wrappers running in --verbose mode can parse the debug stderr text for "not retryable" or "x-should-retry": "false". But this is fragile and depends on debug output format staying stable.
Context
- Claude CLI version: 2.1.73
- Anthropic SDK version: 0.74.0
- Incident log: https://gist.github.com/konard/6be043cca61d023154e4e2eb53c0148e
- Related: https://github.com/link-assistant/hive-mind/issues/1437
This issue has 3 comments on GitHub. Read the full discussion on GitHub ↗