BerriAI/litellm · error · GetAccessTokenError

Token exchange response missing fields: {data}

Error message

Token exchange response missing fields: {data}

What it means

Raised as `GetAccessTokenError` (status 400) when the token-exchange response is HTTP 200 but missing any of `access_token`, `refresh_token`, or `id_token`. Indicates OpenAI's token endpoint returned an unexpected payload shape (e.g. an error body with 200, or an API change).

Source

Thrown at litellm/llms/chatgpt/authenticator.py:278

                CHATGPT_OAUTH_TOKEN_URL,
                headers={"Content-Type": "application/x-www-form-urlencoded"},
                content=body,
            )
            resp.raise_for_status()
            data: Final = resp.json()
        except httpx.HTTPStatusError as exc:
            raise GetAccessTokenError(
                message=f"Token exchange failed: {exc}",
                status_code=exc.response.status_code,
            )
        except Exception as exc:
            raise GetAccessTokenError(
                message=f"Token exchange failed: {exc}",
                status_code=400,
            )

        if not all(key in data for key in ("access_token", "refresh_token", "id_token")):
            raise GetAccessTokenError(
                message=f"Token exchange response missing fields: {data}",
                status_code=400,
            )
        return {
            "access_token": data["access_token"],
            "refresh_token": data["refresh_token"],
            "id_token": data["id_token"],
        }

    def _refresh_tokens(self, refresh_token: str) -> dict[str, str]:
        try:
            client: Final = _get_httpx_client()
            resp: Final = client.post(
                CHATGPT_OAUTH_TOKEN_URL,
                json={
                    "client_id": CHATGPT_CLIENT_ID,
                    "grant_type": "refresh_token",
                    "refresh_token": refresh_token,

View on GitHub (pinned to 6c2dcb801b)

Solutions

  1. Read the embedded response body in the message — it usually contains an `error` field explaining the omission.
  2. Upgrade litellm to pick up parsing fixes for the current API contract.
  3. Retry the login from scratch; transient incomplete responses do occur.
  4. If the body shows a consent/scope error, complete the flow in a browser profile with the right account permissions.
Defensive patterns

Strategy: try-catch

Try / catch

try:
    tokens = authenticator._exchange_code_for_tokens(code_data)
except GetAccessTokenError as e:
    if "missing fields" in str(e):
        log.error("token endpoint returned: %s", e.message)  # contains raw body
    raise

Prevention

When it happens

Trigger: Completing device login where the token endpoint returns 200 with a partial or error-shaped JSON (missing the three required keys); the full raw body is embedded in the message for diagnosis.

Common situations: litellm lagging behind an OpenAI auth API change; scopes/consent changes causing the server to omit tokens; proxy interference rewriting the response.

Related errors


AI-assisted analysis of BerriAI/litellm@6c2dcb801b (2026-08-15). Data as JSON: /api/errors/64194c308214574d. Report an issue: GitHub.