Hmbown/CodeWhale · error

Anthropic API error (HTTP {status} {error_type}): {message}

Error message

Anthropic API error (HTTP {status} {error_type}): {message}

What it means

`check_anthropic_response` is the shared status gate for streaming and non-streaming Anthropic Messages calls: on a non-2xx it reads the body (64KB cap), parses the `{type, message}` error envelope via `parse_anthropic_error_envelope`, records the failure for the request-health/circuit-breaker logic (`mark_request_failure`), and bails with `HTTP {status} {error_type}: {message}`. When the body is not an Anthropic envelope, the type/message fall back to generic values.

Source

Thrown at crates/tui/src/client/anthropic.rs:237

            .send()
            .await
            .context("Anthropic Messages API request failed")?;
        self.check_anthropic_response(response).await
    }

    /// Shared status/error-envelope handling for streaming and
    /// non-streaming Messages responses.
    async fn check_anthropic_response(
        &self,
        response: reqwest::Response,
    ) -> Result<reqwest::Response> {
        let status = response.status();
        if !status.is_success() {
            let raw = bounded_error_text(response, ERROR_BODY_MAX_BYTES).await;
            let (error_type, message) = parse_anthropic_error_envelope(&raw);
            self.mark_request_failure(&format!("anthropic status={status}"))
                .await;
            anyhow::bail!("Anthropic API error (HTTP {status} {error_type}): {message}");
        }
        self.mark_request_success().await;
        Ok(response)
    }

    /// Open the streaming Messages request through the shared stream-entry
    /// transport policy: bounded header wait, dual-client selection, and at
    /// most one HTTP/1.1 fallback retry on a classified H2 header stall.
    /// Wire-specific request construction (headers, endpoint, body) stays
    /// here at the adapter edge.
    async fn open_anthropic_stream_response(
        &self,
        url: &str,
        body: &Value,
    ) -> Result<reqwest::Response> {
        let url = self.messages_transport_url(url);
        let open_req = super::stream_entry::StreamOpenRequest::new(
            super::stream_entry::stream_open_timeout(),

View on GitHub (pinned to 8880682c63)

Solutions

  1. Match the `error_type` in the message: `authentication_error` → fix the API key; `invalid_request_error` → fix the named parameter/model; `rate_limit_error` → back off and retry later; `overloaded_error`/5xx → retry with backoff.
  2. Verify the model id still exists on the Anthropic model catalog.
  3. For 429s, reduce request frequency or concurrency; for context-size 400s, trim or compact the conversation.
  4. If using a proxy, compare its error envelope with the official Anthropic shape — mismatched envelopes degrade this message but the status still tells you the class.
Defensive patterns

Strategy: retry

Type guard

fn is_retryable_anthropic_status(status: u16) -> bool {
    matches!(status, 408 | 429 | 500 | 502 | 503 | 529 | 524)
}

Try / catch

let mut attempt = 0;
loop {
    attempt += 1;
    match client.create_message(req.clone()).await {
        Ok(resp) => break Ok(resp),
        Err(e) => {
            let msg = e.to_string();
            if msg.contains("HTTP 429") || msg.contains("529") || msg.contains("HTTP 5") {
                if attempt >= MAX_RETRIES { break Err(e); }
                tokio::time::sleep(backoff(attempt)).await; // exponential + jitter
                continue;
            }
            if msg.contains("HTTP 401") || msg.contains("authentication_error") { fix_key_and_stop(); }
            break Err(e); // 400 invalid_request: fix the request, do not retry
        }
    }
}

Prevention

When it happens

Trigger: 401 `authentication_error` (bad `x-api-key`/authorization header); 400 `invalid_request_error` (malformed tools, bad `max_tokens`, unsupported parameter for the model); 404 model not found; 413 oversize prompt; 429 `rate_limit_error`; 529 `overloaded_error`; 5xx `api_error`. Each also feeds failure-streak tracking, so repeated failures can trip the client's failure marking.

Common situations: Expired or copied-with-whitespace API key; requesting a retired model id after Anthropic deprecations; hitting org rate limits during bulk sessions; anthropic-compatible proxies (Bedrock/frontier gateways) returning their own envelope shapes; long prompts exceeding context limits surfaced as 400.

Related errors


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