Hmbown/CodeWhale · error · anyhow::Error
Failed to call Chat Completions API: HTTP
Error message
Failed to call {} Chat Completions API: HTTP {status}: {error_text} What it means
A non-streaming Chat Completions request returned a non-success HTTP status. The bounded error body is sanitized with the provider display name and re-raised with the status, so this is the generic surface for every upstream Chat Completions API error (auth, quota, bad request, model not found). Raised in `create_message_chat` in `crates/tui/src/client/chat.rs` around line 1303, reached via `create_message_with_cache_policy`.
Solutions
- Read the sanitized provider `error_text` in the message and fix the named cause.
- Verify API key and model access for `self.api_provider`.
- For 429, add backoff/retry; for 5xx, retry later or switch provider.
- For 400, validate the messages/tools payload (often context-length or schema issues).
Defensive patterns
Strategy: retry
Validate before calling
fn chat_request_precheck(api_key: &str, model: &str, messages: &[Value]) -> Result<(), String> {
if api_key.trim().is_empty() { return Err("missing API key".into()); }
if messages.is_empty() { return Err("empty messages".into()); }
Ok(())
} Try / catch
match client.create_message(req).await {
Err(e) if e.to_string().contains("Chat Completions API: HTTP") => {
match extract_status(&e.to_string()) {
429 | 500..=599 => retry_with_backoff().await,
401 | 403 => Err(anyhow!("check provider key/model access: {e}")),
_ => Err(e),
}
}
other => other,
} Prevention
- Verify API key and model entitlement before non-stream calls.
- Back off on 429 and provider 5xx.
- Validate messages fit the model's context window.
- Confirm the base URL resolves to the correct provider path.
When it happens
Trigger: Any non-2xx from POST `{base_url}/chat/completions`: 401 invalid API key, 403 no model access, 404 unknown model, 429 rate limit, 400 invalid request body (bad messages/tools/payload), 5xx provider outage.
Common situations: Wrong or expired API keys; model names not available on the configured provider/plan; payloads exceeding context limits; provider-side incidents; misconfigured base URLs hitting a path that 404s.
Understand the failure class
Background: "API error: {status}" and "HTTP 401/403/404/429/5xx" errors: non-2xx HTTP responses explained — this error's family across 27 libraries.
Related errors
- Anthropic API error (HTTP )
- Cloud agent sandbox listing failed
- Cloudflare SQL request failed
- CNB pull request create failed
- Codewhale account request failed
AI-assisted analysis of Hmbown/CodeWhale@73e0f67d83 (2026-09-22).
Data as JSON: /api/errors/c6093304699478cf.
Report an issue: GitHub.
Appendix: source
Thrown at crates/tui/src/client/chat.rs:1303
None
};
// The endpoint was resolved by the shared seam alongside the body, so
// a route-shape decision (e.g. DeepSeek's strict-tools `/beta` path)
// cannot be made twice with two different answers.
let url = prepared.endpoint.url.as_str();
let response = self.send_json_with_retry(url, body).await?;
let status = response.status();
crate::client::record_provider_response(self.api_provider, status.as_u16());
if !status.is_success() {
let raw_error_text = bounded_error_text(response, ERROR_BODY_MAX_BYTES).await;
let error_text = sanitize_http_error_body(
Some(self.api_provider.display_name()),
status.as_u16(),
&raw_error_text,
);
anyhow::bail!(
"Failed to call {} Chat Completions API: HTTP {status}: {error_text}",
self.api_provider.display_name()
);
}
let response_text = response
.text()
.await
.context("Failed to read Chat API response body")?;
let value: Value =
serde_json::from_str(&response_text).context("Failed to parse Chat API JSON")?;
let parsed = parse_chat_message_for_route(&value, self.api_provider, &self.base_url)?;
if let Some(key) = response_cache_key {
crate::llm_response_cache::response_cache().put(key, parsed.clone());
}
Ok(parsed)
}
}View on GitHub (pinned to 73e0f67d83)