Most API error handling is built around one assumption: the HTTP status code tells you whether the request worked. A 200 means success; a 429 or 529 means failure. Streaming breaks that assumption. When you set "stream": true on a Claude Messages API request, the server commits to an HTTP status before generation finishes. It returns 200, opens a stream of server-sent events (SSE — a standard where the server pushes a sequence of small text events over one long-lived HTTP response), and starts sending tokens. Anything that goes wrong after that point cannot change the status code you already received. Instead, Anthropic's docs are explicit: on streaming requests, an error can occur after the 200 response, and it arrives as an error event inside the stream rather than as an HTTP status.
What an in-stream error looks like
A mid-stream error is just another SSE event, with a JSON body like this:
{"type": "error", "error": {"type": "overloaded_error", "message": "Overloaded"}}
That particular example — overloaded_error — is the streaming equivalent of the HTTP 529 status a non-streaming request would have received. A 529 reflects API-wide high traffic on Anthropic's side, not a problem with your request, and the standard guidance applies: retry with exponential backoff, consider a less heavily loaded model, or spread requests out over time. Other faults can surface the same way; the key point is that the same failure has two delivery mechanisms depending on when it happens relative to the response headers.
Two failure paths, one policy
It helps to think of every streaming request as having two distinct failure surfaces:
| Pre-response failure | Mid-stream failure | |
|---|---|---|
| Delivered as | HTTP status code (429, 500, 529, …) with a JSON error body | An error event inside the SSE stream, after HTTP 200 |
| When it happens | Before generation starts | After tokens have started flowing |
| What you have so far | Nothing | Possibly a partial response already shown to a user or written downstream |
The retry policy should be the same for both: per Anthropic's error documentation, 429s, 5xx-class errors, and connection errors are retryable with exponential backoff, while 400/401/403/404/413 indicate a request you need to fix, not resend. The official SDKs auto-retry retryable request errors (twice by default, honoring the retry-after header). What changes mid-stream is the cleanup: a retry means issuing a fresh request and regenerating from the start, so anything you already rendered or persisted from the dead stream needs to be discarded or clearly marked incomplete before the retry's output replaces it.
Know what a healthy stream looks like
You can only detect an unhealthy stream if you know the healthy shape. A complete stream follows a documented event flow: message_start, then for each content block a content_block_start, one or more content_block_delta events, and a content_block_stop, then one or more message_delta events, and finally a single message_stop. Two practical rules fall out of that:
Treat message_stop as the success signal. A stream that ends — whether via an error event or a dropped connection — without message_stop did not finish, no matter how much text arrived first. "The connection closed" and "the response completed" are different facts.
Log the request-id before you need it. Every response carries a request-id header (error bodies also include a request_id field). Capture it when the stream opens, not when it fails, so that support escalations for mid-stream deaths have something to reference.
message_stop means done. Everything else — error events, silence, connection resets — routes to the same retry-or-surface logic as an HTTP-level failure.A note on the third-party platforms
Streaming itself is available on all four 3P platforms — Claude Platform on AWS, Amazon Bedrock, Google Vertex AI, and Microsoft Foundry. The event anatomy described here is documented for the Claude API's SSE format, which is also what the current "Claude in Amazon Bedrock" surface serves; Bedrock's legacy InvokeModelWithResponseStream path instead wraps output in AWS's own event-stream encoding, so error delivery details there follow AWS's documentation. Wherever you run, the architectural lesson is identical: build a failure path for events that arrive after the 200.
Where to go next
For the full event vocabulary, see streaming event types; for the status-code side of the ledger, see API error codes. Long quiet stretches between events are normal — ping events explains how the API keeps the connection alive through them.