mirror of
https://github.com/instructkr/claw-code.git
synced 2026-06-05 22:17:10 +08:00
fix: retry 400 responses with transient gateway error bodies
Some providers/proxies return HTTP 400 with bodies like "no parseable body" or "connection reset" during transient network blips. These are not real bad requests — they're gateway errors wearing a 400 mask. Detect known gateway error phrases in 400 response bodies and mark them as retryable so the existing exponential backoff handles them.
This commit is contained in:
@@ -924,6 +924,22 @@ const fn is_retryable_status(status: reqwest::StatusCode) -> bool {
|
||||
matches!(status.as_u16(), 408 | 409 | 429 | 500 | 502 | 503 | 504)
|
||||
}
|
||||
|
||||
/// Some providers return HTTP 400 with an unparseable body when a gateway
|
||||
/// or proxy flakes (e.g. "HTTP 400 from backend (no parseable body)").
|
||||
/// These are transient network blips, not actual bad requests, and should
|
||||
/// be retried. We detect them by checking the body for known gateway error
|
||||
/// phrases.
|
||||
fn is_retryable_400(status: reqwest::StatusCode, body: &str) -> bool {
|
||||
if status != reqwest::StatusCode::BAD_REQUEST {
|
||||
return false;
|
||||
}
|
||||
let lowered = body.to_ascii_lowercase();
|
||||
lowered.contains("no parseable body")
|
||||
|| lowered.contains("connection reset")
|
||||
|| lowered.contains("broken pipe")
|
||||
|| lowered.contains("empty reply from server")
|
||||
}
|
||||
|
||||
/// Anthropic API keys (`sk-ant-*`) are accepted over the `x-api-key` header
|
||||
/// and rejected with HTTP 401 "Invalid bearer token" when sent as a Bearer
|
||||
/// token via `ANTHROPIC_AUTH_TOKEN`. This happens often enough in the wild
|
||||
|
||||
@@ -1682,6 +1682,21 @@ const fn is_retryable_status(status: reqwest::StatusCode) -> bool {
|
||||
matches!(status.as_u16(), 408 | 409 | 429 | 500 | 502 | 503 | 504)
|
||||
}
|
||||
|
||||
/// Some providers return HTTP 400 with an unparseable body when a gateway
|
||||
/// or proxy flakes (e.g. "HTTP 400 from backend (no parseable body)").
|
||||
/// These are transient network blips, not actual bad requests, and should
|
||||
/// be retried.
|
||||
fn is_retryable_400(status: reqwest::StatusCode, body: &str) -> bool {
|
||||
if status != reqwest::StatusCode::BAD_REQUEST {
|
||||
return false;
|
||||
}
|
||||
let lowered = body.to_ascii_lowercase();
|
||||
lowered.contains("no parseable body")
|
||||
|| lowered.contains("connection reset")
|
||||
|| lowered.contains("broken pipe")
|
||||
|| lowered.contains("empty reply from server")
|
||||
}
|
||||
|
||||
/// Generate a suggested user action based on the HTTP status code and error context.
|
||||
/// This provides actionable guidance when API requests fail.
|
||||
fn suggested_action_for_status(status: reqwest::StatusCode) -> Option<String> {
|
||||
|
||||
Reference in New Issue
Block a user