{"record":{"id":"f813045a443e92f4","repo":"xai-org/grok-build","slug":"device-code-request-failed-http-status-body","errorCode":null,"errorMessage":"Device code request failed (HTTP {status}): {body}","messagePattern":"Device code request failed \\(HTTP (.+?)\\): (.+?)","errorType":"http","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/codegen/xai-grok-shell/src/auth/device_code.rs","lineNumber":166,"sourceCode":"            // headless automation in the device-flow funnel metrics.\n            .header(\"x-grok-client-surface\", surface.as_str())\n            .form(&[\n                (\"client_id\", client_id),\n                (\"scope\", scope_str.as_str()),\n                (\"referrer\", \"grok-build\"),\n            ]),\n        &url,\n    )\n    .send()\n    .await?;\n\n    if !resp.status().is_success() {\n        let status = resp.status();\n        let body = resp.text().await.unwrap_or_default();\n        if status.as_u16() == 404 {\n            anyhow::bail!(DeviceCodeError::NotEnabled);\n        }\n        anyhow::bail!(\"Device code request failed (HTTP {status}): {body}\");\n    }\n\n    let server_resp: DeviceCodeResponse = resp.json().await?;\n\n    // Defend against control characters from a malicious issuer.\n    if !server_resp\n        .user_code\n        .chars()\n        .all(|c| c.is_ascii_alphanumeric() || c == '-')\n    {\n        anyhow::bail!(\"Server returned invalid user_code format (expected [A-Z0-9-])\");\n    }\n\n    validate_verification_uri(&server_resp.verification_uri)?;\n    if let Some(ref verification_uri_complete) = server_resp.verification_uri_complete {\n        validate_verification_uri(verification_uri_complete)?;\n    }\n","sourceCodeStart":148,"sourceCodeEnd":184,"githubUrl":"https://github.com/xai-org/grok-build/blob/bc7f02eddd3d84085849dc19ed216f11c23b0571/crates/codegen/xai-grok-shell/src/auth/device_code.rs#L148-L184","documentation":"request_device_code treats any non-success, non-404 HTTP status from the device-code endpoint as a hard failure, including the status code and up-to-the-full response body in the message. This surfaces server-side rejection details (rate limits, bad client config, outages) to the caller of run_device_code_login_channels.","triggerScenarios":"Calling request_device_code when the endpoint returns non-2xx other than 404 — e.g. 401/403 (client auth rejected), 429 (rate limited), 5xx (server error) — with the response body embedded in the error.","commonSituations":"Auth server outage or maintenance, incorrect client_id/audience configured server-side, exceeding device-code issuance rate limits, or a reverse proxy returning 502/503.","solutions":["Inspect the HTTP status and body in the message: 5xx → retry with backoff; 429 → wait and retry; 401/403 → fix client/deployment auth config","Verify the device-code endpoint configuration (client_id, scopes, base URL)","Check auth service health/status page before repeated retries","Fall back to `grok login` or XAI_API_KEY while the endpoint is unhealthy"],"exampleFix":null,"handlingStrategy":"retry","validationCode":null,"typeGuard":null,"tryCatchPattern":"match request_device_code(&client, &cfg).await {\n    Ok(dc) => dc,\n    Err(e) => {\n        let msg = e.to_string();\n        if msg.contains(\"HTTP 429\") || msg.contains(\"HTTP 5\") {\n            tokio::time::sleep(Duration::from_secs(5)).await;\n            request_device_code(&client, &cfg).await?\n        } else {\n            return Err(e); // 401/403: config problem, don't retry\n        }\n    },\n}","preventionTips":["Retry only transient statuses (429, 5xx); fail fast on 401/403","Monitor auth service health before initiating logins","Validate client_id/endpoint config server-side to avoid repeated rejections"],"tags":["auth","device-code","http","network"],"backgroundTag":"device-code-request-failed","analyzedSha":"bc7f02eddd3d84085849dc19ed216f11c23b0571","analyzedAt":"2026-08-31T04:59:42.031Z","schemaVersion":2},"datasetVersion":"2026-08-31T09:17:48.483Z"}