{"record":{"id":"1bdf43cb4be16b72","repo":"zeroclaw-labs/zeroclaw","slug":"openai-device-code-authorization-was-denied","errorCode":null,"errorMessage":"OpenAI device-code authorization was denied","messagePattern":"OpenAI device-code authorization was denied","errorType":"exception","errorClass":"anyhow::Error","httpStatus":null,"severity":"warning","filePath":"crates/zeroclaw-providers/src/auth/openai_oauth.rs","lineNumber":210,"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\n        if let Ok(err) = serde_json::from_str::<OAuthErrorResponse>(&text) {\n            match err.error.as_str() {\n                \"authorization_pending\" => {\n                    continue;\n                }\n                \"slow_down\" => {\n                    interval_secs = interval_secs.saturating_add(5);\n                    continue;\n                }\n                \"access_denied\" => {\n                    anyhow::bail!(\"OpenAI device-code authorization was denied\")\n                }\n                \"expired_token\" => {\n                    anyhow::bail!(\"OpenAI device-code expired\")\n                }\n                _ => {\n                    anyhow::bail!(\n                        \"OpenAI device-code polling failed ({status}): {}\",\n                        err.error_description.unwrap_or(err.error)\n                    )\n                }\n            }\n        }\n\n        anyhow::bail!(\"OpenAI device-code polling failed ({status}): {text}\");\n    }\n}\n\npub async fn receive_loopback_code(expected_state: &str, timeout: Duration) -> Result<String> {","sourceCodeStart":192,"sourceCodeEnd":228,"githubUrl":"https://github.com/zeroclaw-labs/zeroclaw/blob/88bb9c8533fc57ed7a03e36ca7c9ed2bf8336dcc/crates/zeroclaw-providers/src/auth/openai_oauth.rs#L192-L228","documentation":"While polling the OpenAI token endpoint, the response carried the OAuth error code access_denied — the user (or a policy) actively rejected the consent screen for the device code. This is a terminal outcome for the flow: polling stops immediately rather than continuing until expiry.","triggerScenarios":"The user clicks 'Deny'/'Cancel' on the OpenAI device consent page while `zeroclaw auth login --model-provider openai-codex --device-code` is polling; or an org policy auto-denies the requested scopes.","commonSituations":"Consent screens showing suspicious-app warnings that scare users into denying, organizational SSO policies blocking the app, or the wrong browser account being used so the user denies in confusion.","solutions":["Re-run the login and choose Allow on the consent screen, signing in with the account that should own the token","If an org policy denies the app, use a personal/authorized account or have an admin allowlist the client","Confirm the user_code belongs to your terminal session before approving, so you are not denying another flow"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"match openai_oauth::poll_device_code_tokens(&client, &device).await {\n    Err(e) if e.to_string().contains(\"authorization was denied\") => {\n        // user intent: do not retry, surface guidance and stop\n        anyhow::bail!(\"consent was denied — re-run `auth login --device-code` and choose Allow\");\n    }\n    other => other,\n}","preventionTips":["Tell the user which account will receive the token before they open the consent page","For org accounts, confirm the app is allowlisted before starting the flow"],"tags":["oauth2","device-code","openai","access-denied","consent"],"backgroundTag":"oauth-access-denied","analyzedSha":"88bb9c8533fc57ed7a03e36ca7c9ed2bf8336dcc","analyzedAt":"2026-08-23T01:07:41.857Z","schemaVersion":2},"datasetVersion":"2026-08-23T08:06:27.607Z"}