{"record":{"id":"8fb64b2465560b87","repo":"usestrix/strix","slug":"no-account-id","errorCode":"no_account_id","errorMessage":"no_account_id: could not read chatgpt_account_id from token","messagePattern":"no_account_id: could not read chatgpt_account_id from token","errorType":"error_code","errorClass":"CodexAuthError","httpStatus":null,"severity":"error","filePath":"strix/config/codex.py","lineNumber":256,"sourceCode":"    return data\n\n\ndef _record_from_token_response(\n    data: dict[str, Any], refresh_fallback: str | None = None\n) -> dict[str, Any]:\n    access = data.get(\"access_token\")\n    # A refresh response may omit refresh_token when it isn't rotated; keep the old one.\n    refresh = data.get(\"refresh_token\") or refresh_fallback\n    expires_in = data.get(\"expires_in\")\n    if not isinstance(access, str) or not access:\n        raise CodexAuthError(\"bad_response\", \"token response missing access_token\")\n    if not isinstance(refresh, str) or not refresh:\n        raise CodexAuthError(\"bad_response\", \"token response missing refresh_token\")\n    account_id = _account_id_from_jwt(access) or _account_id_from_jwt(\n        data.get(\"id_token\") if isinstance(data.get(\"id_token\"), str) else \"\"\n    )\n    if not account_id:\n        raise CodexAuthError(\"no_account_id\", \"could not read chatgpt_account_id from token\")\n    ttl = expires_in if isinstance(expires_in, int | float) else 3600\n    return {\n        \"type\": \"oauth\",\n        \"provider\": PROVIDER,\n        \"access\": access,\n        \"refresh\": refresh,\n        \"account_id\": account_id,\n        \"expires_at\": time.time() + ttl,\n    }\n\n\ndef exchange_code(code: str, verifier: str) -> dict[str, Any]:\n    data = _post_form(\n        {\n            \"grant_type\": \"authorization_code\",\n            \"client_id\": CLIENT_ID,\n            \"code\": code,\n            \"code_verifier\": verifier,","sourceCodeStart":238,"sourceCodeEnd":274,"githubUrl":"https://github.com/usestrix/strix/blob/85513391305171ecc6faffe03da4a8bda5e3febb/strix/config/codex.py#L238-L274","documentation":"CodexAuthError with code `no_account_id` raised when Strix cannot extract `chatgpt_account_id` from either the access token JWT or the id_token JWT. Strix needs the account ID to route inference to the right ChatGPT backend account, so it refuses to save an unusable credential.","triggerScenarios":"During login or refresh: `_account_id_from_jwt(access)` and `_account_id_from_jwt(id_token)` both return None — the JWT payload's `https://api.openai.com/auth` claim is absent or malformed (e.g. opaque/non-JWT access tokens, or claim shape changed).","commonSituations":"OpenAI changing token claims for the Codex backend; account types (e.g. free-tier or enterprise) whose tokens lack the claim; a Strix version that predates a claim-shape change by OpenAI.","solutions":["Update Strix to the latest release — claim-parsing fixes track OpenAI changes quickly","Re-login (`strix auth logout && strix auth login`) to obtain freshly-shaped tokens","Decode your token (jwt.io or `base64 -d` on the payload segment) and check the `https://api.openai.com/auth` claim exists; if absent, the account/token type is unsupported for Codex auth — use an API key provider instead","Report upstream with the decoded claim shape (never paste the token itself)"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":"def codex_record_usable(record: dict) -> bool:\n    return bool(\n        isinstance(record, dict)\n        and record.get(\"type\") == \"oauth\"\n        and record.get(\"access\")\n        and record.get(\"refresh\")\n        and record.get(\"account_id\")\n    )","tryCatchPattern":"from strix.config.codex import CodexAuthError\n\ntry:\n    access, account = get_valid_token()\nexcept CodexAuthError as e:\n    if e.code == \"no_account_id\":\n        # token shape unsupported — re-login; if persistent, switch to API-key provider\n        ...","preventionTips":["Keep Strix updated — chatgpt_account_id claim parsing tracks OpenAI token changes","After login failures with no_account_id, decode the token payload and verify the auth claim exists before filing issues","Use API-key providers for account types whose tokens lack the Codex claim"],"tags":["oauth","auth","jwt","codex","account"],"backgroundTag":null,"analyzedSha":"85513391305171ecc6faffe03da4a8bda5e3febb","analyzedAt":"2026-08-15T05:03:57.275Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}