{"record":{"id":"5ab749d3abbd42c6","repo":"unslothai/unsloth","slug":"device-authorization-failed-enable-device-code-lo","errorCode":null,"errorMessage":"Device authorization failed. Enable device-code login in ChatGPT settings and retry.","messagePattern":"Device authorization failed\\. Enable device-code login in ChatGPT settings and retry\\.","errorType":"exception","errorClass":"CodexAuthError","httpStatus":400,"severity":"error","filePath":"studio/backend/core/inference/openai_codex_auth.py","lineNumber":454,"sourceCode":"                try:\n                    error_body = response.json()\n                    error = error_body.get(\"error\")\n                    error_code = (\n                        error.get(\"code\", \"\") if isinstance(error, dict) else str(error or \"\")\n                    )\n                    server_interval = error_body.get(\"interval\")\n                except Exception:\n                    pass\n                if error_code == \"deviceauth_authorization_pending\":\n                    continue\n                if error_code == \"slow_down\" or response.status_code == 429:\n                    try:\n                        requested = float(server_interval)\n                    except (TypeError, ValueError):\n                        requested = flow.interval + 5\n                    flow.interval = min(30.0, max(flow.interval + 5, requested))\n                    continue\n                raise CodexAuthError(\n                    \"Device authorization failed. Enable device-code login in ChatGPT settings and retry.\"\n                )\n            body = response.json()\n            code = body.get(\"authorization_code\")\n            verifier = body.get(\"code_verifier\")\n            if (\n                not isinstance(code, str)\n                or not code\n                or not isinstance(verifier, str)\n                or not verifier\n            ):\n                raise CodexAuthError(\"ChatGPT returned an invalid device authorization response.\")\n            await _exchange_code(\n                flow,\n                code,\n                verifier = verifier,\n                redirect_uri = OPENAI_CODEX_DEVICE_REDIRECT_URI,\n            )","sourceCodeStart":436,"sourceCodeEnd":472,"githubUrl":"https://github.com/unslothai/unsloth/blob/203007d19051dcd2ae33876786d117c99f6b0368/studio/backend/core/inference/openai_codex_auth.py#L436-L472","documentation":"Raised as CodexAuthError in the device-code polling loop when the token endpoint returns a terminal (non-pending, non-slow_down) error. Only deviceauth_authorization_pending and slow_down/429 are treated as continue conditions; every other error or status >= 400 aborts device login with this message. The text specifically points at the most common root cause: device-code login being disabled for the ChatGPT account.","triggerScenarios":"Polling OPENAI_CODEX_TOKEN_URL during device flow and receiving errors such as 'deviceauth_access_denied', 'expired_token' (device code timed out), 'invalid_client', or any unrecognized error code while grant_type is the device authorization exchange.","commonSituations":"ChatGPT account/plan does not have device-code login enabled (work/edu accounts where it is admin-disabled); the user waited past the device code expiry before approving; OpenAI disables the codex device grant for the account; server-side policy changes to the device authorization endpoint.","solutions":["Enable device-code login in ChatGPT settings (the error text names this directly) and retry the device flow.","If the device code expired (user waited too long), restart the flow and approve promptly at the verification URL.","Fall back to the browser loopback flow when device login is administratively unavailable.","If it persists after enabling, log the actual error_code from the response to identify the exact server rejection."],"exampleFix":"// before\nflow = await codex_auth.start_device_flow(provider_id, persist_bundle)\n# user approves late; device code expired; polling raises and flow dies\n\n// after\ntry:\n    flow = await codex_auth.start_device_flow(provider_id, persist_bundle)\nexcept codex_auth.CodexAuthError as exc:\n    if \"device-code login\" in str(exc):\n        flow = await codex_auth.start_browser_flow(provider_id, persist_bundle)  # fallback path","handlingStrategy":"fallback","validationCode":null,"typeGuard":"def is_device_flow_error(exc: BaseException) -> bool:\n    return isinstance(exc, codex_auth.CodexAuthError) and \"device-code login\" in str(exc)","tryCatchPattern":"try:\n    flow = await start_device_flow(provider_id, persist_bundle)\nexcept codex_auth.CodexAuthError as exc:\n    if \"device-code login\" in str(exc):\n        flow = await start_browser_flow(provider_id, persist_bundle)  # fallback\n    else:\n        raise","preventionTips":["Enable device-code login in ChatGPT account settings before choosing the device flow.","Approve the device prompt at the verification URL promptly — codes expire.","Offer the browser flow as an automatic alternative.","Log the upstream error_code to distinguish 'disabled' from 'expired token'."],"tags":["oauth","device-flow","chatgpt","codex","account-settings"],"backgroundTag":null,"analyzedSha":"203007d19051dcd2ae33876786d117c99f6b0368","analyzedAt":"2026-08-15T02:48:39.846Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}