{"record":{"id":"35017fab3bcba40d","repo":"mastra-ai/mastra","slug":"failed-to-extract-chatgpt-account-id-from-openai-c","errorCode":null,"errorMessage":"Failed to extract ChatGPT account id from OpenAI Codex token","messagePattern":"Failed to extract ChatGPT account id from OpenAI Codex token","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"mastracode/sdk/src/auth/providers/openai-codex.ts","lineNumber":138,"sourceCode":"  if (!payload) return null;\n  const accountId = payload.chatgpt_account_id ?? payload[JWT_CLAIM_PATH]?.chatgpt_account_id;\n  return typeof accountId === 'string' && accountId.length > 0 ? accountId : null;\n}\n\nfunction getAccountId(tokens: { idToken?: string; access: string }, fallback?: string): string | undefined {\n  const fromIdToken = tokens.idToken ? extractAccountIdFromClaims(decodeJwt(tokens.idToken)) : null;\n  if (fromIdToken) return fromIdToken;\n\n  const fromAccessToken = extractAccountIdFromClaims(decodeJwt(tokens.access));\n  if (fromAccessToken) return fromAccessToken;\n\n  return fallback;\n}\n\nfunction requireAccountId(tokens: { idToken?: string; access: string }, fallback?: string): string {\n  const accountId = getAccountId(tokens, fallback);\n  if (!accountId) {\n    throw new Error('Failed to extract ChatGPT account id from OpenAI Codex token');\n  }\n  return accountId;\n}\n\ntype TokenResponseJson = {\n  id_token?: string;\n  access_token?: string;\n  refresh_token?: string;\n  expires_in?: number;\n};\n\nfunction tokenResponseToResult(json: TokenResponseJson, logPrefix: string): TokenResult {\n  if (!json.access_token || !json.refresh_token) {\n    console.error(`[openai-codex] ${logPrefix} response missing fields:`, json);\n    return { type: 'failed' };\n  }\n\n  return {","sourceCodeStart":120,"sourceCodeEnd":156,"githubUrl":"https://github.com/mastra-ai/mastra/blob/75dd419e613fe9c39f846ffc500716141b74fda6/mastracode/sdk/src/auth/providers/openai-codex.ts#L120-L156","documentation":"OpenAI Codex tokens carry the ChatGPT account id inside the JWT (id_token/access token claims). requireAccountId extracts it via getAccountId, allowing an explicit fallback, and throws if neither the token claims nor the fallback yield an account id — because downstream Codex API calls require the ChatGPT account id header/claim.","triggerScenarios":"Calling accountId or completing pollCodexDeviceLogin with tokens whose id_token/access JWT lacks the expected chatgpt_account_id / account id claim, no fallback supplied, or a token that failed to decode (malformed/truncated JWT).","commonSituations":"Logging in with an API-key-only or non-ChatGPT account whose token lacks the claim; corrupted or hand-truncated stored tokens; OpenAI changing the JWT claim structure; passing tokens obtained outside this library.","solutions":["Re-run the Codex device login to obtain fresh tokens that include the account id claim","Supply the account id explicitly via the fallback parameter if you know it","Inspect the token: decode the JWT payload (middle segment) and check for the account id claim to confirm the cause","Check for an OpenAI token-format change and update the SDK"],"exampleFix":"// before\nconst id = requireAccountId(tokens); // throws when claim missing\n// after\nconst id = requireAccountId(tokens, process.env.CHATGPT_ACCOUNT_ID); // explicit fallback","handlingStrategy":"fallback","validationCode":"// Decode the JWT payload and check for the account id claim before calling\ndef decodeJwtPayload(token) {\n  const part = token?.split('.')[1];\n  if (!part) return null;\n  try { return JSON.parse(Buffer.from(part, 'base64url').toString('utf8')); } catch { return null;\n  }\n}\nconst claims = decodeJwtPayload(tokens.idToken ?? tokens.access);\nconst accountId = claims?.chatgpt_account_id ?? fallback;","typeGuard":"function hasAccountIdClaim(tokens: { idToken?: string; access: string }): boolean {\n  const payload = decodeJwtPayloadSafe(tokens.idToken ?? tokens.access);\n  return typeof payload?.['chatgpt_account_id'] === 'string' && !!payload['chatgpt_account_id'];\n}","tryCatchPattern":"try {\n  const accountId = provider.accountId();\n} catch (err) {\n  if (err instanceof Error && err.message.includes('Failed to extract ChatGPT account id')) {\n    await login('openai-codex'); // mint fresh tokens that include the claim\n  } else throw err;\n}","preventionTips":["Re-login rather than hand-copying tokens from other tools — external tokens may lack the claim","Never truncate stored JWTs; keep the credential blob intact","Supply the account id via the fallback parameter when you have it out-of-band","Track OpenAI token/JWT claim changes and keep the SDK current"],"tags":["auth","jwt","token-parsing","openai-codex"],"backgroundTag":"jwt-claim-missing","analyzedSha":"75dd419e613fe9c39f846ffc500716141b74fda6","analyzedAt":"2026-08-30T00:15:31.844Z","schemaVersion":2},"datasetVersion":"2026-08-30T03:17:51.788Z"}