{"record":{"id":"f38902e58c326532","repo":"can1357/oh-my-pi","slug":"the-selected-chatgpt-credential-is-not-a-valid-jwt","errorCode":null,"errorMessage":"The selected ChatGPT credential is not a valid JWT","messagePattern":"The selected ChatGPT credential is not a valid JWT","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/coding-agent/src/security/cloud.ts","lineNumber":161,"sourceCode":"\tconst currentStep = optionalString(raw.current_step);\n\tif (currentStep) configuration.currentStep = currentStep;\n\tconst scanType = optionalString(scanInput.scan_type);\n\tif (scanType) configuration.scanType = scanType;\n\tconst remainingScans = typeof raw.scans_remaining === \"number\" ? raw.scans_remaining : raw.remaining_scans;\n\tif (typeof remainingScans === \"number\" && Number.isFinite(remainingScans))\n\t\tconfiguration.remainingScans = remainingScans;\n\tif (typeof raw.total_scans === \"number\" && Number.isFinite(raw.total_scans))\n\t\tconfiguration.totalScans = raw.total_scans;\n\tconst createdAt = optionalString(raw.created_at);\n\tif (createdAt) configuration.createdAt = createdAt;\n\tconst updatedAt = optionalString(raw.updated_at);\n\tif (updatedAt) configuration.updatedAt = updatedAt;\n\treturn configuration;\n}\n\nfunction jwtSubject(accessToken: string): string {\n\tconst claims = decodeJwt(accessToken);\n\tif (!claims) throw new Error(\"The selected ChatGPT credential is not a valid JWT\");\n\treturn requiredString(claims.sub ?? claims.user_id, \"authenticated user id\");\n}\n\nexport class CodexSecurityCloudHttpError extends Error {\n\tconstructor(\n\t\treadonly status: number,\n\t\treadonly endpoint: string,\n\t) {\n\t\tsuper(`Codex Security cloud request failed (${status}) at ${endpoint}`);\n\t\tthis.name = \"CodexSecurityCloudHttpError\";\n\t}\n}\n\ninterface CloudRequestOptions {\n\tmethod?: \"GET\" | \"POST\";\n\tquery?: Record<string, string | number | undefined>;\n\tbody?: JsonObject | ((accessToken: string) => JsonObject);\n\tsignal?: AbortSignal;","sourceCodeStart":143,"sourceCodeEnd":179,"githubUrl":"https://github.com/can1357/oh-my-pi/blob/969062200754ea02cfac922e5ebb8c608c079e15/packages/coding-agent/src/security/cloud.ts#L143-L179","documentation":"jwtSubject() decodes the ChatGPT OAuth access token to extract the authenticated user id (sub or user_id claim). If the access token is not a decodable JWT, this error is thrown — the stored credential's access token is malformed or in an unexpected format.","triggerScenarios":"decodeJwt(accessToken) returns null: the pinned openai-codex credential's access token is not a JWT (corrupted storage, wrong token type stored, token truncated by an export/import).","commonSituations":"Manually edited or migrated auth storage; credential written by an older/newer client storing a non-JWT token; copy-paste truncation when seeding credentials.","solutions":["Re-authenticate with the provider so a fresh, valid access token is stored","Delete the malformed credential and log in again","Inspect the stored access token (should be three dot-separated base64url segments) to confirm corruption"],"exampleFix":"// before\nconst subject = jwtSubject(account.accessToken); // throws\n// after\nawait authStorage.refreshOrReauthenticate(provider); // obtain fresh JWT\nconst subject = jwtSubject(freshAccessToken);","handlingStrategy":"validation","validationCode":"function looksLikeJwt(token: string): boolean {\n  const parts = token.split(\".\");\n  return parts.length === 3 && parts.every(p => p.length > 0);\n}\nif (!looksLikeJwt(accessToken)) throw new Error(\"Stored access token is not a JWT\");","typeGuard":"function isJwt(token: string): boolean {\n  const parts = token.split(\".\");\n  if (parts.length !== 3) return false;\n  try { JSON.parse(atob(parts[1].replace(/-/g, \"+\").replace(/_/g, \"/\"))); return true; }\n  catch { return false; }\n}","tryCatchPattern":"try {\n  const scan = await client.startScan(input);\n} catch (err) {\n  if (err.message.includes(\"not a valid JWT\")) {\n    await reauthenticate(\"openai-codex\"); // replace corrupted token\n  } else throw err;\n}","preventionTips":["Never hand-edit auth storage token fields","Re-authenticate rather than importing tokens manually","Validate token shape after any credential migration"],"tags":["jwt","oauth","corrupt-token"],"backgroundTag":"invalid-jwt-token","analyzedSha":"969062200754ea02cfac922e5ebb8c608c079e15","analyzedAt":"2026-08-31T10:29:35.737Z","schemaVersion":2},"datasetVersion":"2026-08-31T14:17:45.589Z"}