{"record":{"id":"9705d100c9ace64a","repo":"zeroclaw-labs/zeroclaw","slug":"xai-device-code-polling-failed-status","errorCode":null,"errorMessage":"xAI device-code polling failed ({status}): {}","messagePattern":"xAI device-code polling failed \\((.+?)\\): (.+?)","errorType":"exception","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"crates/zeroclaw-providers/src/auth/xai_oauth.rs","lineNumber":311,"sourceCode":"\n        if response.status().is_success() {\n            return parse_token_response(response).await;\n        }\n\n        let status = response.status();\n        let text = response.text().await.unwrap_or_default();\n        if let Ok(err) = serde_json::from_str::<OAuthErrorResponse>(&text) {\n            match err.error.as_str() {\n                \"authorization_pending\" => continue,\n                \"slow_down\" => {\n                    interval_secs = interval_secs.saturating_add(5);\n                    continue;\n                }\n                \"access_denied\" | \"authorization_denied\" => {\n                    anyhow::bail!(\"xAI device-code authorization was denied\")\n                }\n                \"expired_token\" => anyhow::bail!(\"xAI device-code expired\"),\n                _ => anyhow::bail!(\n                    \"xAI device-code polling failed ({status}): {}\",\n                    err.error_description.unwrap_or(err.error)\n                ),\n            }\n        }\n        anyhow::bail!(\"xAI device-code polling failed ({status}): {text}\");\n    }\n}\n\nasync fn parse_token_response(response: reqwest::Response) -> Result<TokenSet> {\n    let status = response.status();\n    let body = response.text().await.unwrap_or_default();\n    if !status.is_success() {\n        if let Ok(err) = serde_json::from_str::<OAuthErrorResponse>(&body) {\n            anyhow::bail!(\n                \"xAI OAuth token request failed ({status}): {}\",\n                err.error_description.unwrap_or(err.error)\n            );","sourceCodeStart":293,"sourceCodeEnd":329,"githubUrl":"https://github.com/zeroclaw-labs/zeroclaw/blob/88bb9c8533fc57ed7a03e36ca7c9ed2bf8336dcc/crates/zeroclaw-providers/src/auth/xai_oauth.rs#L293-L329","documentation":"`poll_device_code_tokens` received a structured OAuth error it does not special-case — everything except authorization_pending, slow_down, access_denied/authorization_denied, and expired_token. The endpoint's `error_description` (or bare `error`) is embedded with the HTTP status. Codes like `invalid_grant` (bad or replayed device_code) or `invalid_client` land here.","triggerScenarios":"Polling with a device_code from a different client or an older session; xAI rejecting the urn:ietf:params:oauth:grant-type:device_code grant or the client_id; unexpected provider-side error codes.","commonSituations":"Reusing a stale `DeviceCodeStart` across process restarts; provider changes to the device grant; fixtures with hardcoded device codes.","solutions":["Read the embedded error code: `invalid_grant` usually means the device_code is stale — start a fresh flow","Use one consistent set of discovery results and client constants for the whole flow","For unrecognized codes, check xAI status/changelog — the grant may have changed"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":"fn is_device_poll_error(e: &anyhow::Error) -> bool {\n    e.to_string().contains(\"xAI device-code polling failed\")\n}","tryCatchPattern":"match poll_device_code_tokens(&client, &ep, &device).await {\n    Ok(t) => t,\n    Err(e) if is_device_poll_error(&e) && e.to_string().contains(\"invalid_grant\") => {\n        let device = start_device_code_flow(&client, &dev_ep).await?; // stale device_code\n        poll_device_code_tokens(&client, &ep, &device).await?\n    }\n    Err(e) => return Err(e),\n}","preventionTips":["Use one DeviceCodeStart per flow; never reuse it across restarts","Keep discovery results and client constants consistent within a flow","Log the raw embedded error code for provider escalation"],"tags":["oauth","xai","device-code","polling","http","rust"],"backgroundTag":"oauth-device-code-polling-failed","analyzedSha":"88bb9c8533fc57ed7a03e36ca7c9ed2bf8336dcc","analyzedAt":"2026-08-23T01:07:41.857Z","schemaVersion":2},"datasetVersion":"2026-08-23T08:06:27.607Z"}