Hmbown/CodeWhale · error
Anthropic stream error ({error_type}): {message}
Error message
Anthropic stream error ({error_type}): {message} What it means
The Anthropic SSE stream delivered an `error` event after the HTTP 200 response had already begun. The client converts it via `convert_anthropic_sse_data`, extracts `error.type` and `error.message` with `anthropic_error_fields` (defaulting to "unknown" and the raw JSON), yields this error, and terminates the stream with an early `return`. The connection itself was healthy; the provider reported the failure mid-generation.
Source
Thrown at crates/tui/src/client/anthropic.rs:358
let line = match super::take_sse_line(&mut buffer) {
Ok(Some(line)) => line,
Ok(None) => break,
Err(err) => {
yield Err(anyhow::anyhow!("{err}"));
return;
}
};
// `event:` lines are redundant (the data payload carries
// `type`) and comment/heartbeat lines are ignorable.
let Some(data) = super::extract_sse_data_value(&line) else {
continue;
};
match convert_anthropic_sse_data(data) {
Some(Ok(StreamEvent::Error { error })) => {
let (error_type, message) = anthropic_error_fields(&error);
yield Err(anyhow::anyhow!(
"Anthropic stream error ({error_type}): {message}"
));
return;
}
Some(Ok(event)) => {
let is_stop = matches!(event, StreamEvent::MessageStop);
yield Ok(event);
if is_stop {
return;
}
}
Some(Err(e)) => {
logging::warn(format!("Failed to parse Anthropic SSE event: {e}"));
}
None => {}
}
}
}View on GitHub (pinned to 8880682c63)
Solutions
- Read the error_type in parentheses: retry with exponential backoff for `overloaded_error`, `rate_limit_error`, and generic `api_error`
- For `invalid_request_error`, fix the request per the embedded message (tool schema, max_tokens, model name) — retrying will not help
- Check status.anthropic.com before retrying when the type is `overloaded_error`
- If the stop is content-policy related, adjust the prompt or tool descriptions instead of retrying
Example fix
// before
while let Some(ev) = stream.next().await {
if let Ok(event) = ev { handle(event); }
}
// after
while let Some(item) = stream.next().await {
match item {
Ok(event) => handle(event),
Err(e) if is_retryable_anthropic_stream_error(&e.to_string()) => {
backoff_and_reopen_stream().await;
}
Err(e) => return Err(e),
}
} Defensive patterns
Strategy: retry
Type guard
fn is_retryable_anthropic_stream_error(msg: &str) -> bool {
msg.starts_with("Anthropic stream error")
&& (msg.contains("overloaded_error")
|| msg.contains("rate_limit_error")
|| msg.contains("api_error"))
} Try / catch
match stream.next().await {
Some(Err(e)) if is_retryable_anthropic_stream_error(&e.to_string()) => {
backoff().await;
stream = client.reopen_stream(request).await?;
}
Some(Err(e)) => return Err(e), // invalid_request_error and similar are permanent
Some(Ok(event)) => handle(event),
None => break,
} Prevention
- Keep request rate below Anthropic rate limits, especially for long streaming turns
- Treat `invalid_request_error` as a request bug — fix the payload, never retry it
- Monitor for `overloaded_error` bursts before they become hard failures
When it happens
Trigger: Anthropic sends `data: {"type":"error",...}` mid-stream: `overloaded_error` (529 capacity), `rate_limit_error` hit while tokens stream, `invalid_request_error` detected only after headers were sent, or a content/safety stop during generation.
Common situations: Sustained request volume tripping rate limits mid-response; Anthropic capacity incidents; prompts or tool schemas accepted at request time but rejected during generation; long streaming turns during provider degradation.
Related errors
- Stream read error: {e}
- SSE stream idle timeout after {}s — no data received (bytes_
- {err}
- Runtime API request failed (${status}): ${message}
- Runtime API request failed (${status}): ${message}
AI-assisted analysis of Hmbown/CodeWhale@8880682c63 (2026-08-16).
Data as JSON: /api/errors/cecbe53d2dd8134b.
Report an issue: GitHub.