{"record":{"id":"7c86e145d75a2be1","repo":"unslothai/unsloth","slug":"chatgpt-authorization-failed-please-reconnect","errorCode":null,"errorMessage":"ChatGPT authorization failed. Please reconnect.","messagePattern":"ChatGPT authorization failed\\. Please reconnect\\.","errorType":"exception","errorClass":"CodexAuthError","httpStatus":400,"severity":"error","filePath":"studio/backend/core/inference/openai_codex_auth.py","lineNumber":281,"sourceCode":"            response = await client.post(OPENAI_CODEX_TOKEN_URL, data = data)\n    except httpx.HTTPError as exc:\n        raise CodexAuthError(\"Could not reach ChatGPT authentication.\") from exc\n    if response.status_code >= 400:\n        error_code = \"\"\n        try:\n            error = response.json().get(\"error\")\n            error_code = error.get(\"code\", \"\") if isinstance(error, dict) else str(error or \"\")\n        except Exception:\n            pass\n        if data.get(\"grant_type\") == \"refresh_token\" and error_code in {\n            \"invalid_grant\",\n            \"invalid_refresh_token\",\n            \"refresh_token_expired\",\n        }:\n            raise CodexReauthorizationRequired(\n                \"ChatGPT authorization is no longer valid. Please reconnect.\"\n            )\n        raise CodexAuthError(\"ChatGPT authorization failed. Please reconnect.\")\n    try:\n        return response.json()\n    except Exception as exc:\n        raise CodexAuthError(\"ChatGPT returned an invalid authorization response.\") from exc\n\n\nasync def _exchange_code(\n    flow: OAuthFlow,\n    code: str,\n    *,\n    verifier: str | None = None,\n    redirect_uri: str | None = None,\n) -> None:\n    if flow.consumed:\n        raise CodexAuthError(\"Authorization callback was already used.\")\n    flow.consumed = True\n    try:\n        body = await _token_request(","sourceCodeStart":263,"sourceCodeEnd":299,"githubUrl":"https://github.com/unslothai/unsloth/blob/203007d19051dcd2ae33876786d117c99f6b0368/studio/backend/core/inference/openai_codex_auth.py#L263-L299","documentation":"Raised as CodexAuthError when a POST to the OAuth token endpoint returns HTTP >= 400 but the error is NOT one of the known refresh-token failure codes (or the request was not a refresh_token grant at all). It is the generic terminal failure for token exchange and refresh: bad authorization codes, wrong client_id/redirect_uri, malformed requests, or unrecognized server error codes all land here.","triggerScenarios":"Calling _token_request/_exchange_code with an invalid, already-used, or expired authorization_code; a redirect_uri that does not match the one used at consent; a PKCE code_verifier that does not match the challenge; the server returning an error object with an unexpected code such as 'invalid_client' or 'unauthorized_client'; any 5xx from auth.openai.com during token exchange.","commonSituations":"The user copied only part of the callback URL so the code is truncated; the authorization flow was started in one process and completed in another so the PKCE verifier is missing; OpenAI changed the client id or endpoint constants; a proxy or auth library mangles the request body; clock skew or replayed codes after a retry.","solutions":["Start a fresh authorization flow (old codes and verifiers are single-use); do not retry the same code.","Verify the authorization request and token request used the same redirect_uri and that the full callback URL (including query string) was used.","Inspect response body logging (temporarily) to read the actual error code from OpenAI and map it to the cause.","Confirm OPENAI_CODEX_CLIENT_ID and token endpoint constants are current for your library version."],"exampleFix":"// before\nbody = await _token_request({\n    \"grant_type\": \"authorization_code\",\n    \"client_id\": OPENAI_CODEX_CLIENT_ID,\n    \"code\": code_from_user_input.strip().split(\"?\")[0],  # truncated code\n    ...\n})\n\n// after\nbody = await _token_request({\n    \"grant_type\": \"authorization_code\",\n    \"client_id\": OPENAI_CODEX_CLIENT_ID,\n    \"code\": code,  # full, unmodified code taken from the exact callback URL\n    ...\n})","handlingStrategy":"try-catch","validationCode":null,"typeGuard":"def is_codex_auth_error(exc: BaseException) -> bool:\n    return isinstance(exc, codex_auth.CodexAuthError) and not isinstance(\n        exc, codex_auth.CodexReauthorizationRequired\n    )","tryCatchPattern":"try:\n    await codex_auth.complete_browser_flow(provider_id, flow_id, callback_url)\nexcept codex_auth.CodexAuthError as exc:\n    if isinstance(exc, codex_auth.CodexReauthorizationRequired):\n        raise  # different remedy: reconnect\n    show_error(\"Authorization failed, please start a new connection.\")","preventionTips":["Use each authorization code exactly once; never retry a failed exchange with the same code.","Keep the authorization request and token exchange within the same flow object (matching redirect_uri and PKCE verifier).","Copy callback URLs completely — truncated codes cause invalid_grant-style 400s.","Keep the library updated so OAuth client constants match OpenAI's current values."],"tags":["oauth","authentication","http-400","token-exchange","codex"],"backgroundTag":null,"analyzedSha":"203007d19051dcd2ae33876786d117c99f6b0368","analyzedAt":"2026-08-15T02:48:39.846Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}