Include x-should-retry signal in structured result event output

Resolved 💬 3 comments Opened Mar 17, 2026 by konard Closed Apr 16, 2026

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

View original on GitHub ↗

This issue has 3 comments on GitHub. Read the full discussion on GitHub ↗