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
- 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.
- Verify the model id still exists on the Anthropic model catalog.
- For 429s, reduce request frequency or concurrency; for context-size 400s, trim or compact the conversation.
- 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
- Never retry 400 invalid_request_error — read the named parameter and fix the request payload.
- Honor 429 rate-limit windows from the error message; use exponential backoff with jitter for 429/529/5xx.
- Track model deprecations and update model ids before they 404.
- Keep prompts under context limits by compacting conversations proactively.
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
- iLink API ${endpoint} failed: HTTP ${response.status} — ${te
- failed to fetch {description} from {url}: HTTP {status} {bod
- Failed to list models: HTTP {status}: {error_text}
- Speech synthesis failed: HTTP {status}: {error_text}
- FIM API error: HTTP {status}: {error_text}
AI-assisted analysis of Hmbown/CodeWhale@8880682c63 (2026-08-16).
Data as JSON: /api/errors/1f24b3b238f29655.
Report an issue: GitHub.