{"record":{"id":"30b188e6f07133f2","repo":"unslothai/unsloth","slug":"chatgpt-returned-an-invalid-token-response","errorCode":null,"errorMessage":"ChatGPT returned an invalid token response.","messagePattern":"ChatGPT returned an invalid token response\\.","errorType":"exception","errorClass":"CodexAuthError","httpStatus":400,"severity":"error","filePath":"studio/backend/core/inference/openai_codex_auth.py","lineNumber":209,"sourceCode":"    parts = access_token.split(\".\")\n    if len(parts) < 2 or len(parts[1]) > 16_384:\n        raise CodexAuthError(\"ChatGPT returned an invalid access token.\")\n    try:\n        raw = base64.urlsafe_b64decode(parts[1] + \"=\" * (-len(parts[1]) % 4))\n        payload = json.loads(raw)\n    except Exception as exc:\n        raise CodexAuthError(\"ChatGPT returned an invalid access token.\") from exc\n    account_id = payload.get(\"https://api.openai.com/auth\", {}).get(\"chatgpt_account_id\")\n    if not isinstance(account_id, str) or not account_id or len(account_id) > 512:\n        account_id = payload.get(\"https://api.openai.com/auth.chatgpt_account_id\")\n    if not isinstance(account_id, str) or not account_id or len(account_id) > 512:\n        raise CodexAuthError(\"The ChatGPT account identifier was missing.\")\n    return account_id\n\n\ndef _validate_token_payload(body: Any, previous_refresh_token: str = \"\") -> dict[str, Any]:\n    if not isinstance(body, dict):\n        raise CodexAuthError(\"ChatGPT returned an invalid token response.\")\n    access_token = body.get(\"access_token\")\n    refresh_token = body.get(\"refresh_token\") or previous_refresh_token\n    expires_in = body.get(\"expires_in\", 3600)\n    if not isinstance(access_token, str) or not access_token:\n        raise CodexAuthError(\"ChatGPT returned an invalid token response.\")\n    if not isinstance(refresh_token, str) or not refresh_token:\n        raise CodexAuthError(\"ChatGPT did not return a refresh token.\")\n    try:\n        expires_in = max(60, min(int(expires_in), 30 * 24 * 3600))\n    except (TypeError, ValueError) as exc:\n        raise CodexAuthError(\"ChatGPT returned an invalid token lifetime.\") from exc\n    return {\n        \"access_token\": access_token,\n        \"refresh_token\": refresh_token,\n        \"expires_at\": int(time.time()) + expires_in,\n        \"account_id\": extract_chatgpt_account_id(access_token),\n    }\n","sourceCodeStart":191,"sourceCodeEnd":227,"githubUrl":"https://github.com/unslothai/unsloth/blob/203007d19051dcd2ae33876786d117c99f6b0368/studio/backend/core/inference/openai_codex_auth.py#L191-L227","documentation":"First validation in _validate_token_payload: the body returned by the ChatGPT token endpoint must be a dict (a JSON object). If the response parsed to a list, string, number, or None (e.g. the endpoint returned a JSON array or a plain error string with HTTP 200-ish handling), the extractor cannot read access_token/refresh_token fields and raises this CodexAuthError.","triggerScenarios":"The token endpoint (OPENAI_CODEX_TOKEN_URL) responding with a non-object JSON body — array, scalar, or null — which httpx .json() happily parses but isinstance(body, dict) rejects.","commonSituations":"A proxy or captive portal intercepting the auth request and returning odd JSON; upstream API change; an error envelope that is itself a list; testing with mocked responses shaped incorrectly.","solutions":["Retry the OAuth/token request — a transient intermediary (proxy, captive portal) producing malformed bodies often clears.","If reproducible, capture the raw response body/status to confirm whether the endpoint or an intermediary is misbehaving, and report/adjust.","For tests/mocks, make the fake token response a JSON object with access_token/refresh_token/expires_in."],"exampleFix":null,"handlingStrategy":"type-guard","validationCode":"if not isinstance(body, dict):\n    raise ValueError(f'expected JSON object from token endpoint, got {type(body).__name__}')","typeGuard":"def is_token_body(body: object) -> TypeGuard[dict]:\n    return isinstance(body, dict)","tryCatchPattern":"try:\n    bundle = _validate_token_payload(body)\nexcept CodexAuthError as e:\n    if 'invalid token response' in str(e):\n        log_raw_response_shape(body)  # never log token values\n        retry_or_reauth()\n    else:\n        raise","preventionTips":["Shape-check mocked token responses in tests as JSON objects with the three fields.","Alert when the token endpoint returns non-object bodies — it usually means an intermediary is interfering.","Validate at the HTTP layer too: unexpected status + body combos should abort early."],"tags":["oauth","api-contract","response-validation","codex"],"backgroundTag":null,"analyzedSha":"203007d19051dcd2ae33876786d117c99f6b0368","analyzedAt":"2026-08-15T02:48:39.846Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}