BerriAI/litellm · error · GetAccessTokenError
Polling failed
Error message
Polling failed: {exc} What it means
GetAccessTokenError raised while polling the ChatGPT device-authorization endpoint: the poll returned an HTTPStatusError whose code is not 403/404 (those two are retried as 'keep waiting'). The message contains the underlying httpx error and the authenticator attaches the upstream status code, so you can tell a 400 (expired/invalid device code) from a 5xx (upstream incident).
Solutions
- Restart the login flow to get a fresh device code and approve it promptly at the printed verify URL
- If the status is 429, slow down — do not run multiple logins concurrently from the same host
- Upgrade litellm if the poll endpoint contract changed
- Check the status code embedded in the message to distinguish stale-code (400) from upstream failure (5xx)
Defensive patterns
Strategy: retry
Try / catch
from litellm.llms.chatgpt.authenticator import GetAccessTokenError
try:
tokens = authenticator.login()
except GetAccessTokenError as e:
if "Polling failed" in str(e) and e.status_code in (400, 429):
# stale device code or rate limit: restart with a fresh code
tokens = authenticator.login() # prompts a new device code
else:
raise Prevention
- Approve the device code immediately after it is printed
- Run only one device login at a time per host
- Treat repeated 429s as a signal to back off, not to loop faster
When it happens
Trigger: Polling CHATGPT_DEVICE_CODE_URL during device login and receiving e.g. 400 (device_auth_id expired or invalid), 401, or 500 — any non-403/404 error status aborts with this error.
Common situations: User took too long to approve and the device code went stale mid-poll; rate-limited polling; auth.openai.com incidents; reused device_auth_id from a previous login attempt.
Related errors
- Device code response missing fields
- Failed to request device code
- Timed out waiting for device authorization
- Token exchange failed
- Token exchange response missing fields
AI-assisted analysis of BerriAI/litellm@77b7c6c40c (2026-08-18).
Data as JSON: /api/errors/4debe053960bba9e.
Report an issue: GitHub.
Appendix: source
Thrown at litellm/llms/chatgpt/authenticator.py:232
if all(
key in data
for key in (
"authorization_code",
"code_challenge",
"code_verifier",
)
):
return data
if resp.status_code in (403, 404):
time.sleep(max(interval, DEVICE_CODE_POLL_SLEEP_SECONDS))
continue
resp.raise_for_status()
except httpx.HTTPStatusError as exc:
status_code = exc.response.status_code if exc.response else None
if status_code in (403, 404):
time.sleep(max(interval, DEVICE_CODE_POLL_SLEEP_SECONDS))
continue
raise GetAccessTokenError(
message=f"Polling failed: {exc}",
status_code=exc.response.status_code,
)
except Exception as exc:
raise GetAccessTokenError(
message=f"Polling failed: {exc}",
status_code=400,
)
time.sleep(max(interval, DEVICE_CODE_POLL_SLEEP_SECONDS))
raise GetAccessTokenError(
message="Timed out waiting for device authorization",
status_code=408,
)
def _exchange_code_for_tokens(self, code_data: dict[str, str]) -> dict[str, str]:
try:
client: Final = _get_httpx_client()View on GitHub (pinned to 77b7c6c40c)