{"record":{"id":"64194c308214574d","repo":"BerriAI/litellm","slug":"token-exchange-response-missing-fields-data","errorCode":null,"errorMessage":"Token exchange response missing fields: {data}","messagePattern":"Token exchange response missing fields: (.+?)","errorType":"exception","errorClass":"GetAccessTokenError","httpStatus":400,"severity":"error","filePath":"litellm/llms/chatgpt/authenticator.py","lineNumber":278,"sourceCode":"                CHATGPT_OAUTH_TOKEN_URL,\n                headers={\"Content-Type\": \"application/x-www-form-urlencoded\"},\n                content=body,\n            )\n            resp.raise_for_status()\n            data: Final = resp.json()\n        except httpx.HTTPStatusError as exc:\n            raise GetAccessTokenError(\n                message=f\"Token exchange failed: {exc}\",\n                status_code=exc.response.status_code,\n            )\n        except Exception as exc:\n            raise GetAccessTokenError(\n                message=f\"Token exchange failed: {exc}\",\n                status_code=400,\n            )\n\n        if not all(key in data for key in (\"access_token\", \"refresh_token\", \"id_token\")):\n            raise GetAccessTokenError(\n                message=f\"Token exchange response missing fields: {data}\",\n                status_code=400,\n            )\n        return {\n            \"access_token\": data[\"access_token\"],\n            \"refresh_token\": data[\"refresh_token\"],\n            \"id_token\": data[\"id_token\"],\n        }\n\n    def _refresh_tokens(self, refresh_token: str) -> dict[str, str]:\n        try:\n            client: Final = _get_httpx_client()\n            resp: Final = client.post(\n                CHATGPT_OAUTH_TOKEN_URL,\n                json={\n                    \"client_id\": CHATGPT_CLIENT_ID,\n                    \"grant_type\": \"refresh_token\",\n                    \"refresh_token\": refresh_token,","sourceCodeStart":260,"sourceCodeEnd":296,"githubUrl":"https://github.com/BerriAI/litellm/blob/77b7c6c40c0c5aa5fbcb1d6a1825ac39ca8829b8/litellm/llms/chatgpt/authenticator.py#L260-L296","documentation":"GetAccessTokenError (status 400) raised when the ChatGPT token endpoint returned 200 and parseable JSON, but the body is missing any of access_token, refresh_token, or id_token. litellm requires all three before building the auth record, so a response without the full token set is treated as a failed exchange. The raw payload is echoed in the message.","triggerScenarios":"The token endpoint responding 200 with a partial payload — e.g. only an error sub-object or an id_token-less body; a proxy/mock rewriting the response; an OpenAI schema change the installed litellm predates.","commonSituations":"Stale litellm versions after OpenAI alters the OAuth token response; test harnesses mocking the token endpoint incompletely; middleware injecting modified responses on auth domains.","solutions":["Upgrade litellm to the latest version so token parsing matches the current response schema","Bypass any proxy/mock in front of auth.openai.com and retry","Inspect the {data} payload printed in the message to see exactly which token is absent","If it persists, restart the device login to get a fresh, well-formed exchange"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"from litellm.llms.chatgpt.authenticator import GetAccessTokenError\n\ntry:\n    tokens = authenticator.login()\nexcept GetAccessTokenError as e:\n    if \"missing fields\" in str(e):\n        print(\"Token response schema changed; upgrade litellm (pip install -U litellm).\")\n    raise","preventionTips":["Upgrade litellm promptly when OpenAI auth endpoints change behavior","Do not intercept auth.openai.com with test doubles in production paths","Log (redacted) auth failures so schema regressions are visible early"],"tags":["chatgpt","oauth","token-exchange","schema-mismatch","auth"],"backgroundTag":"oauth-token-exchange-failed","analyzedSha":"77b7c6c40c0c5aa5fbcb1d6a1825ac39ca8829b8","analyzedAt":"2026-08-18T11:44:31.656Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}