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

  1. Read the error_type in parentheses: retry with exponential backoff for `overloaded_error`, `rate_limit_error`, and generic `api_error`
  2. For `invalid_request_error`, fix the request per the embedded message (tool schema, max_tokens, model name) — retrying will not help
  3. Check status.anthropic.com before retrying when the type is `overloaded_error`
  4. 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

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


AI-assisted analysis of Hmbown/CodeWhale@8880682c63 (2026-08-16). Data as JSON: /api/errors/cecbe53d2dd8134b. Report an issue: GitHub.