{"record":{"id":"443c600fa58d5c75","repo":"mastra-ai/mastra","slug":"token-exchange-failed","errorCode":null,"errorMessage":"Token exchange failed","messagePattern":"Token exchange failed","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"mastracode/sdk/src/auth/providers/openai-codex.ts","lineNumber":691,"sourceCode":"    // Fallback to onPrompt if still no code\n    if (!code) {\n      const input = await options.onPrompt({\n        message: 'Paste the authorization code (or full redirect URL):',\n      });\n      const parsed = parseAuthorizationInput(input);\n      if (parsed.state && parsed.state !== state) {\n        throw new Error('State mismatch');\n      }\n      code = parsed.code;\n    }\n\n    if (!code) {\n      throw new Error('Missing authorization code');\n    }\n\n    const tokenResult = await exchangeAuthorizationCode(code, verifier, server.redirectUri);\n    if (tokenResult.type !== 'success') {\n      throw new Error('Token exchange failed');\n    }\n\n    const accountId = requireAccountId(tokenResult);\n\n    return {\n      access: tokenResult.access,\n      refresh: tokenResult.refresh,\n      expires: tokenResult.expires,\n      accountId,\n    };\n  } finally {\n    server.close();\n  }\n}\n\nexport const __testing = {\n  createAuthorizationFlow,\n  decodeJwt,","sourceCodeStart":673,"sourceCodeEnd":709,"githubUrl":"https://github.com/mastra-ai/mastra/blob/75dd419e613fe9c39f846ffc500716141b74fda6/mastracode/sdk/src/auth/providers/openai-codex.ts#L673-L709","documentation":"Thrown by the OpenAI Codex OAuth login flow after the user authorizes in the browser and the callback delivers an authorization code. The library called the OAuth token endpoint with exchangeAuthorizationCode and got a non-success result, so it refuses to produce credentials. This means the code-for-token swap at the provider failed (bad code, bad verifier, or provider-side rejection).","triggerScenarios":"Calling login() for the openai-codex provider when exchangeAuthorizationCode(code, verifier, server.redirectUri) returns a result whose type !== 'success' — e.g. the provider returned an OAuth error response instead of tokens.","commonSituations":"The redirect URI registered in the OpenAI app does not match the one used by the local callback server; the user reuses an old/expired authorization code (codes are single-use and short-lived); PKCE verifier/session mismatch from restarting login mid-flow; clock skew or provider outage.","solutions":["Restart the login flow from scratch so a fresh authorization code and matching PKCE verifier are used.","Verify the redirect_uri registered for the OpenAI Codex OAuth app exactly matches the one the local server listens on.","Complete the browser authorization promptly; authorization codes expire in minutes.","Check https://status.openai.com / provider logs for token-endpoint incidents; retry later."],"exampleFix":"// before: re-running a stale login attempt with an old callback URL\nconst code = staleCallbackUrl.searchParams.get('code');\nawait sdk.auth.login('openai-codex', callbacks); // Token exchange failed\n// after: start a clean login and finish it in one session\nawait sdk.auth.login('openai-codex', callbacks); // complete browser auth immediately","handlingStrategy":"try-catch","validationCode":"// before login: ensure no stale in-flight login and app config is sane\nif (!openaiAppRedirectUri.startsWith('http://127.0.0.1') && !openaiAppRedirectUri.startsWith('https://')) {\n  throw new Error('Configure a valid redirect URI registered with the OpenAI app');\n}","typeGuard":"function isTokenExchangeSuccess(r: { type: string }): r is { type: 'success'; access: string } {\n  return r.type === 'success';\n}","tryCatchPattern":"try {\n  await sdk.auth.login('openai-codex', callbacks);\n} catch (e) {\n  if (e instanceof Error && e.message === 'Token exchange failed') {\n    // discard the code/verifier and restart the login flow cleanly\n    await sdk.auth.login('openai-codex', callbacks);\n  }\n}","preventionTips":["Always complete the browser authorization in the same session that started it","Keep the redirect URI identical to the one registered in the OpenAI app","Never reuse authorization codes; codes are single-use and expire in minutes","Retry transient failures once, then restart the full flow"],"tags":["oauth","openai","authentication"],"backgroundTag":"oauth-token-exchange-failed","analyzedSha":"75dd419e613fe9c39f846ffc500716141b74fda6","analyzedAt":"2026-08-30T00:15:31.844Z","schemaVersion":2},"datasetVersion":"2026-08-30T03:17:51.788Z"}