unslothai/unsloth · error · CodexAuthError

The ChatGPT account identifier was missing.

Error message

The ChatGPT account identifier was missing.

What it means

Final check in extract_chatgpt_account_id: after decoding the JWT payload, the ChatGPT account id claim must exist and be a usable string. It is read from payload['https://api.openai.com/auth']['chatgpt_account_id'], with a legacy flat-key fallback ('https://api.openai.com/auth.chatgpt_account_id'); both must be a non-empty string of at most 512 chars. If neither yields a valid id, the account identifier is deemed missing.

Source

Thrown at studio/backend/core/inference/openai_codex_auth.py:203

    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_token
    expires_in = body.get("expires_in", 3600)
    if not isinstance(access_token, str) or not access_token:
        raise CodexAuthError("ChatGPT returned an invalid token response.")
    if not isinstance(refresh_token, str) or not refresh_token:
        raise CodexAuthError("ChatGPT did not return a refresh token.")
    try:
        expires_in = max(60, min(int(expires_in), 30 * 24 * 3600))
    except (TypeError, ValueError) as exc:
        raise CodexAuthError("ChatGPT returned an invalid token lifetime.") from exc
    return {

View on GitHub (pinned to 203007d190)

Solutions

  1. Reconnect via the ChatGPT OAuth flow so the token carries the ChatGPT auth claim — a plain OpenAI API key/token will not have it.
  2. If upstream renamed the claim, update both lookup keys in extract_chatgpt_account_id to the new location.
  3. Log (safely, without the token) which of the two claim paths was absent to distinguish 'wrong token type' from 'claim moved'.
Defensive patterns

Strategy: validation

Validate before calling

auth = payload.get('https://api.openai.com/auth', {})
account_id = auth.get('chatgpt_account_id') if isinstance(auth, dict) else None
if not isinstance(account_id, str) or not account_id:
    raise ValueError('token lacks ChatGPT account claim; needs ChatGPT (not API) OAuth')

Type guard

def token_has_chatgpt_claim(payload: dict) -> bool:
    auth = payload.get('https://api.openai.com/auth')
    return isinstance(auth, dict) and isinstance(auth.get('chatgpt_account_id'), str) and bool(auth['chatgpt_account_id'])

Try / catch

try:
    account_id = extract_chatgpt_account_id(access_token)
except CodexAuthError as e:
    if 'account identifier was missing' in str(e):
        show_message('Connect a ChatGPT account (not an OpenAI API key)')
    else:
        raise

Prevention

When it happens

Trigger: A token from the wrong tenant/product (e.g. a plain OpenAI API token or a platform token without the ChatGPT auth claim), or an upstream claim rename; the claim exists but is empty/null/numeric/over 512 chars in both locations.

Common situations: User authorizes with a non-ChatGPT (API-platform) OpenAI account; OpenAI renames or restructures the auth claim; tokens issued for service principals without a chatgpt_account_id.

Related errors


AI-assisted analysis of unslothai/unsloth@203007d190 (2026-08-15). Data as JSON: /api/errors/9432d6212fc19783. Report an issue: GitHub.