zeroclaw-labs/zeroclaw · error · anyhow::Error
xAI OAuth token request failed ({status}): {body}
Error message
xAI OAuth token request failed ({status}): {body} What it means
Companion of the structured variant in xAI's `parse_token_response`: the token endpoint returned non-2xx and the body did NOT parse as an OAuth error document, so the raw body is embedded with the status. Reached only after the `serde_json::from_str::<OAuthErrorResponse>` attempt fails.
Source
Thrown at crates/zeroclaw-providers/src/auth/xai_oauth.rs:331
err.error_description.unwrap_or(err.error)
),
}
}
anyhow::bail!("xAI device-code polling failed ({status}): {text}");
}
}
async fn parse_token_response(response: reqwest::Response) -> Result<TokenSet> {
let status = response.status();
let body = response.text().await.unwrap_or_default();
if !status.is_success() {
if let Ok(err) = serde_json::from_str::<OAuthErrorResponse>(&body) {
anyhow::bail!(
"xAI OAuth token request failed ({status}): {}",
err.error_description.unwrap_or(err.error)
);
}
anyhow::bail!("xAI OAuth token request failed ({status}): {body}");
}
let parsed: TokenResponse =
serde_json::from_str(&body).context("Failed to parse xAI OAuth token response")?;
let expires_at = parsed
.expires_in
.map(|secs| Utc::now() + chrono::Duration::seconds(secs))
.or_else(|| derive_expires_at_from_jwt(&parsed.access_token));
Ok(TokenSet {
access_token: parsed.access_token,
refresh_token: parsed.refresh_token,
id_token: parsed.id_token,
expires_at,
token_type: parsed.token_type.or_else(|| Some("Bearer".into())),
scope: parsed.scope,
})
}View on GitHub (pinned to 88bb9c8533)
Solutions
- If the body is empty or HTML, suspect the network path — `curl` the token endpoint to compare
- Retry with backoff for 5xx-style responses
- Capture the exact embedded body before escalating to the provider; it identifies the middleman
Defensive patterns
Strategy: retry
Try / catch
match refresh_access_token(&client, &refresh).await {
Ok(t) => t,
Err(e) if e.to_string().contains("xAI OAuth token request failed") && !is_known_oauth_error(&e) => {
retry_with_backoff(refresh_access_token(&client, &refresh)).await? // non-JSON body: suspect the path
}
Err(e) => return Err(e),
} Prevention
- Compare a direct curl to the token endpoint when bodies look like HTML
- Keep egress free of captive portals and rewriting proxies
- Retry only idempotent calls (refresh); never auto-retry code exchange
When it happens
Trigger: An empty body with an error status; HTML returned by proxies, CDNs, or captive portals; malformed or truncated provider responses.
Common situations: TLS-intercepting middleboxes answering for auth.x.ai; provider incidents returning gateway pages; broken egress NAT.
Related errors
- xAI device-code polling failed ({status}): {text}
- xAI OAuth token request failed ({status}): {}
- OpenAI OAuth token request failed ({status}): {body}
- xAI OAuth discovery failed ({status}): {body}
- xAI device-code start failed ({status}): {body}
AI-assisted analysis of zeroclaw-labs/zeroclaw@88bb9c8533 (2026-08-23).
Data as JSON: /api/errors/8ba3140973a565cc.
Report an issue: GitHub.