unslothai/unsloth · error · CodexAuthError
ChatGPT returned an invalid access token.
Error message
ChatGPT returned an invalid access token.
What it means
CodexAuthError from extract_chatgpt_account_id when the access token cannot be treated as a JWT: it must split into at least 2 dot-separated parts with a payload segment no larger than 16,384 chars (a deliberate bound before base64-decoding an untrusted string). Failing the split/size check, or the base64/JSON decode inside the try, both raise 'invalid access token' — the token is malformed, truncated, or not a JWT.
Source
Thrown at studio/backend/core/inference/openai_codex_auth.py:193
bundle["reauthorization_required"] = True
save_oauth_bundle(provider_id, bundle)
def _b64url(data: bytes) -> str:
return base64.urlsafe_b64encode(data).decode("ascii").rstrip("=")
def create_pkce() -> tuple[str, str]:
verifier = _b64url(secrets.token_bytes(48))
challenge = _b64url(hashlib.sha256(verifier.encode("ascii")).digest())
return verifier, challenge
def extract_chatgpt_account_id(access_token: str) -> str:
"""Decode only the bounded JWT payload needed as an upstream routing hint."""
parts = access_token.split(".")
if len(parts) < 2 or len(parts[1]) > 16_384:
raise CodexAuthError("ChatGPT returned an invalid access token.")
try:
raw = base64.urlsafe_b64decode(parts[1] + "=" * (-len(parts[1]) % 4))
payload = json.loads(raw)
except Exception as exc:
raise CodexAuthError("ChatGPT returned an invalid access token.") from exc
account_id = payload.get("https://api.openai.com/auth", {}).get("chatgpt_account_id")
if not isinstance(account_id, str) or not account_id or len(account_id) > 512:
account_id = payload.get("https://api.openai.com/auth.chatgpt_account_id")
if not isinstance(account_id, str) or not account_id or len(account_id) > 512:
raise CodexAuthError("The ChatGPT account identifier was missing.")
return account_id
def _validate_token_payload(body: Any, previous_refresh_token: str = "") -> dict[str, Any]:
if not isinstance(body, dict):
raise CodexAuthError("ChatGPT returned an invalid token response.")
access_token = body.get("access_token")
refresh_token = body.get("refresh_token") or previous_refresh_tokenView on GitHub (pinned to 203007d190)
Solutions
- Inspect the token string: it should look like 'xxxxx.yyyyy.zzzzz' with a decodable middle segment — if not, re-run the OAuth flow to obtain a fresh token.
- Check that nothing in your storage/transport layer truncates or re-encodes the token (column length limits, URL encoding).
- If upstream genuinely changed the token format, update extract_chatgpt_account_id to match the new claim location/format.
Defensive patterns
Strategy: validation
Validate before calling
parts = access_token.split('.')
if len(parts) < 2 or len(parts[1]) > 16_384:
raise ValueError('not a plausible JWT; re-authenticate') Type guard
def looks_like_jwt(token: str) -> bool:
parts = token.split('.')
return len(parts) >= 2 and 0 < len(parts[1]) <= 16_384 Try / catch
try:
account_id = extract_chatgpt_account_id(access_token)
except CodexAuthError as e:
if 'invalid access token' in str(e):
trigger_full_reauth(provider_id) # token unusable; get a new one
else:
raise Prevention
- Check the token shape (dot-separated, bounded payload) before calling extract.
- Store tokens verbatim; never truncate or re-encode them.
- Treat repeated 'invalid access token' as an upstream format change — verify against a known-good token.
When it happens
Trigger: Passing an access token with fewer than 2 dot-separated segments (e.g. an opaque token or truncated string), a payload segment over 16KB, or a payload that is not valid base64url/JSON. Raised during token validation after any successful token exchange.
Common situations: Upstream auth changes where access_token stops being a JWT; string truncation when copying/storing the token; a proxy or logging layer mangling the header; non-ChatGPT OpenAI tokens with a different shape.
Related errors
- The ChatGPT account identifier was missing.
- ChatGPT credential update is busy. Please retry.
- ChatGPT returned an invalid token response.
- ChatGPT did not return a refresh token.
- ChatGPT returned an invalid token lifetime.
AI-assisted analysis of unslothai/unsloth@203007d190 (2026-08-15).
Data as JSON: /api/errors/21f49d757ca1670b.
Report an issue: GitHub.