anthropic stream ended before message_stop
Short answer: treat the response as failed, not finished.
Short answer: treat the response as failed, not finished. A stream that ends before messagestop was cut off mid-flight; retry the whole request and find what closed the connection. 1. Log the last event type you received and whether a messagedelta with a stopreason arrived. If messagedelta arrived but messagestop did not, the break is almost always in transport (proxy, load balancer, or client read loop), not in generation. Expected: you can name the exact event the stream died on. 2. Check the middleboxes. Corporate proxies, CDNs, and ingress controllers commonly kill or buffer long SSE connections on idle timeouts. Disable response buffering for the streaming route and raise idle timeouts above your longest generation. Expected: streams survive past the previous cut-off point. 3. Check your own read loop. Breaking out of the event loop early, a read timeout set for the whole request instead of per-event silence, or a client disconnect downstream all produce this error. Use a silence threshold (no event for N seconds) rather than a total deadline for long outputs. 4. Retry the request from scratch. There is no resume: a truncated stream cannot be continued, and the partial output should be discarded or clearly marked partial, never stored as a completed message. Expected: the retry either completes with messagestop or fails loudly. 5. If it reproduces on short outputs with no proxy in between, capture the request id and check the provider status page; a server-side disconnect is possible but is the last explanation, not the first. Root cause: messagestop is the only completion signal in the Anthropic streaming protocol. Anything that closes the HTTP connection early (idle-timeout intermediaries are the most common, dropped streams run at a fraction of a percent even direct) leaves the client holding a partial message, and strict consumers correctly refuse to call it done. When to use: SDK or hand-rolled SSE consumers of the Anthropic Messages API seeing truncated streaming responses. When NOT to use: a stream that ends with an explicit error event is an API error with its own type and message; handle that instead. A stopreason of maxtokens in messagedelta is a complete, valid stream, not this error. Variant phrasings: "stream ended without messagestop", "claude stream truncated", "anthropic sse connection closed early". Edge cases: tool-use streams carry more events and longer silent gaps while a large inputjson accumulates; size your silence threshold for that. In browsers, an EventSource auto-reconnect can silently restart a request and duplicate output.
Context: A healthy Anthropic Messages stream ends with a fixed event sequence: messagestart, contentblock events, messagedelta (which carries stopreason and final usage), then messagestop. Code that assembles the final message, or a wrapper that validates the stream, reports this error when the connection closes before that terminal messagestop arrives. The partial text received so far is not a completed response, even when it looks finished.