zeroclaw-labs/zeroclaw · warning · anyhow::Error
{err}: {desc}
Error message
{err}: {desc} What it means
The xAI callback query contained an `error` parameter, so `parse_code_from_redirect` fails with `{error}: {error_description}` (default description: "xAI OAuth authorization failed"). This is the IdP reporting that authorization itself failed — no code was ever issued. The classic body is `access_denied: user cancelled...`, but any redirected OAuth error surfaces here.
Source
Thrown at crates/zeroclaw-providers/src/auth/xai_oauth.rs:410
body
);
let _ = stream.write_all(response.as_bytes()).await;
Ok(code)
}
pub fn parse_code_from_redirect(input: &str, expected_state: Option<&str>) -> Result<String> {
let trimmed = input.trim();
if trimmed.is_empty() {
anyhow::bail!("No xAI OAuth code provided");
}
let query = trimmed.split_once('?').map_or(trimmed, |(_, query)| query);
let params = parse_query_params(query);
if let Some(err) = params.get("error") {
let desc = params
.get("error_description")
.cloned()
.unwrap_or_else(|| "xAI OAuth authorization failed".to_string());
anyhow::bail!("{err}: {desc}");
}
if let Some(expected) = expected_state {
let actual = params
.get("state")
.ok_or_else(|| anyhow::Error::msg("xAI OAuth callback missing state parameter"))?;
if actual != expected {
anyhow::bail!("xAI OAuth state mismatch");
}
}
if let Some(code) = params.get("code")
&& !code.trim().is_empty()
{
return Ok(code.trim().to_string());
}
if expected_state.is_none() && !trimmed.contains('=') && !trimmed.contains('?') {
return Ok(trimmed.to_string());
}
anyhow::bail!("xAI OAuth callback missing code parameter")View on GitHub (pinned to 88bb9c8533)
Solutions
- Read the two parts: `access_denied` is user cancellation — offer to restart; other codes indicate config or provider changes
- Restart the flow via `build_authorize_url` with the standard XAI_OAUTH_SCOPE
- For scope failures, verify the account has Grok/API access enabled
Defensive patterns
Strategy: try-catch
Type guard
fn classify_callback_error(e: &anyhow::Error) -> &'static str {
let s = e.to_string();
if s.starts_with("access_denied") { "user-cancelled" } else { "authorization-config-error" }
} Try / catch
match parse_code_from_redirect(path, Some(&pkce.state)) {
Ok(code) => exchange(code),
Err(e) if e.to_string().starts_with("access_denied") => prompt_retry_login().await,
Err(e) if e.to_string().contains(": ") => return Err(e), // provider-redirected error: surface it
Err(e) => return Err(e),
} Prevention
- Classify error-param redirects as user cancellation vs configuration error before retrying
- Verify the account holds grok-cli:access/api:access scopes when denial repeats
- Restart only via build_authorize_url with the standard XAI_OAUTH_SCOPE
When it happens
Trigger: The user cancels at the xAI consent page and the redirect carries `error=access_denied&error_description=...`; scope or client errors redirect with error params instead of a code.
Common situations: User backs out of consent; the account lacks permission for a requested scope (XAI_OAUTH_SCOPE includes grok-cli:access and api:access); client policy changes at the IdP.
Related errors
- xAI device-code authorization was denied
- User denied authorization
- xAI auth profile is not OAuth-based: {profile_id}
- xAI auth profile is missing token set: {profile_id}
- xAI token refresh is in backoff for {remaining}s due to prev
AI-assisted analysis of zeroclaw-labs/zeroclaw@88bb9c8533 (2026-08-23).
Data as JSON: /api/errors/0160e86876a42da0.
Report an issue: GitHub.