BerriAI/litellm · error · RefreshAccessTokenError
Refresh response missing fields: {data}
Error message
Refresh response missing fields: {data} What it means
Raised as `RefreshAccessTokenError` (status 400) when the refresh endpoint returns HTTP 200 but the JSON lacks `access_token` or `id_token`. The server returned an unexpected payload (often an OAuth error object with 200); the raw body is included in the message.
Source
Thrown at litellm/llms/chatgpt/authenticator.py:316
},
)
resp.raise_for_status()
data: Final = resp.json()
except httpx.HTTPStatusError as exc:
raise RefreshAccessTokenError(
message=f"Refresh token failed: {exc}",
status_code=exc.response.status_code,
)
except Exception as exc:
raise RefreshAccessTokenError(
message=f"Refresh token failed: {exc}",
status_code=400,
)
access_token: Final = data.get("access_token")
id_token: Final = data.get("id_token")
if not access_token or not id_token:
raise RefreshAccessTokenError(
message=f"Refresh response missing fields: {data}",
status_code=400,
)
refreshed: Final = {
"access_token": access_token,
"refresh_token": data.get("refresh_token", refresh_token),
"id_token": id_token,
}
auth_data: Final = self._build_auth_record(refreshed)
self._write_auth_file(auth_data)
return refreshed
def _build_auth_record(self, tokens: dict[str, str]) -> dict[str, Any]:
access_token: Final = tokens.get("access_token")
id_token: Final = tokens.get("id_token")
expires_at: Final = self._get_expires_at(access_token) if access_token else None
account_id: Final = self._extract_account_id(id_token or access_token)View on GitHub (pinned to 6c2dcb801b)
Solutions
- Inspect the response body in the error message — an embedded `error` (e.g. `invalid_grant`) means the stored refresh token is dead; re-login.
- Give each deployment/process its own auth file to prevent refresh-token rotation races.
- Upgrade litellm for current refresh handling.
- Add monitoring on this error to detect forced logouts early.
Defensive patterns
Strategy: try-catch
Try / catch
try:
resp = litellm.completion(model="chatgpt/gpt-4o", messages=msgs)
except litellm.AuthenticationError as e:
if "Refresh response missing fields" in str(e) or "invalid_grant" in str(e):
force_relogin() # stored refresh token is consumed/dead
raise Prevention
- Never share one auth file across processes or machines.
- Treat `invalid_grant` in the body as mandatory re-login, not retry.
- Upgrade litellm to track refresh-payload contract changes.
When it happens
Trigger: Token refresh where OpenAI responds 200 with `{"error": "invalid_grant", ...}` or a partial payload missing the two required keys. Common when the refresh token was single-use and already consumed elsewhere.
Common situations: Two processes sharing one auth file: the first refresh rotates the token, the second sends the now-consumed token and gets an error body; OpenAI auth API contract drift; old litellm versions.
Related errors
- Device code response missing fields: {data}
- Token exchange response missing fields: {data}
- Refresh token failed: {exc}
- Failed to request device code: {exc}
- Polling failed: {exc}
AI-assisted analysis of BerriAI/litellm@6c2dcb801b (2026-08-15).
Data as JSON: /api/errors/cc9291e0ebbe1ab7.
Report an issue: GitHub.