{"record":{"id":"da8b6edf782228f6","repo":"mastra-ai/mastra","slug":"state-mismatch","errorCode":null,"errorMessage":"State mismatch","messagePattern":"State mismatch","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"mastracode/sdk/src/auth/providers/openai-codex.ts","lineNumber":646,"sourceCode":"          manualError = err instanceof Error ? err : new Error(String(err));\n          server.cancelWait();\n        });\n\n      const result = await server.waitForCode();\n\n      // If manual input was cancelled, throw that error\n      if (manualError) {\n        throw manualError;\n      }\n\n      if (result?.code) {\n        // Browser callback won\n        code = result.code;\n      } else if (manualCode) {\n        // Manual input won (or callback timed out and user had entered code)\n        const parsed = parseAuthorizationInput(manualCode);\n        if (parsed.state && parsed.state !== state) {\n          throw new Error('State mismatch');\n        }\n        code = parsed.code;\n      }\n\n      // If still no code, wait for manual promise to complete and try that\n      if (!code) {\n        await manualPromise;\n        if (manualError) {\n          throw manualError;\n        }\n        if (manualCode) {\n          const parsed = parseAuthorizationInput(manualCode);\n          if (parsed.state && parsed.state !== state) {\n            throw new Error('State mismatch');\n          }\n          code = parsed.code;\n        }\n      }","sourceCodeStart":628,"sourceCodeEnd":664,"githubUrl":"https://github.com/mastra-ai/mastra/blob/75dd419e613fe9c39f846ffc500716141b74fda6/mastracode/sdk/src/auth/providers/openai-codex.ts#L628-L664","documentation":"During the browser-callback OAuth login, the user-supplied manual authorization input carried a state parameter that does not match the state this login session generated. The library compares parsed.state against the session state to prevent CSRF / authorization-code injection. A mismatch means the pasted code or redirect URL belongs to a different login attempt and is rejected.","triggerScenarios":"In loginOpenAICodex, the manual-input branch (parseAuthorizationInput(manualCode)) yields a non-empty parsed.state different from the generated state — e.g. the user pasted a redirect URL from an older/parallel login, or a second login session's URL.","commonSituations":"Running two `login` commands in parallel and pasting the wrong browser URL; reusing a bookmarked redirect URL from a previous login; copying the callback URL from a stale browser tab after restarting the CLI; misconfigured redirect that points at another app's callback.","solutions":["Re-run the login and paste the redirect URL from the browser tab opened by THIS run (check the state query param matches).","Close stale browser tabs from earlier login attempts before retrying.","If multiple logins run concurrently, serialize them or use separate sessions.","If you control the flow, log the expected state so users can verify before pasting."],"exampleFix":"// before: pasting an old URL\nconst input = 'http://localhost:1455/auth/callback?code=OLD&state=OLD_STATE';\nawait loginOpenAICodex({ onPrompt: () => input });\n\n// after: use the URL from the current attempt\nconst currentUrl = 'http://localhost:1455/auth/callback?code=NEW&state=CURRENT_STATE';\nawait loginOpenAICodex({ onPrompt: () => currentUrl });","handlingStrategy":"validation","validationCode":"function statesMatch(pastedUrl: string, expectedState: string): boolean {\n  const state = new URL(pastedUrl).searchParams.get('state');\n  return !state || state === expectedState;\n}\n// check before passing input to the login call/prompt","typeGuard":null,"tryCatchPattern":"try {\n  await loginOpenAICodex({ onPrompt });\n} catch (e) {\n  if (e.message === 'State mismatch') {\n    console.error('Pasted URL is from a different login session. Restart and use the current URL.');\n  } else throw e;\n}","preventionTips":["Paste redirect URLs only from the browser tab of the current attempt.","Close stale login tabs before re-running login.","Never run two login sessions concurrently in the same environment.","Compare the state query param to the expected state before submitting."],"tags":["oauth","csrf","state-mismatch","security"],"backgroundTag":"oauth-state-mismatch","analyzedSha":"75dd419e613fe9c39f846ffc500716141b74fda6","analyzedAt":"2026-08-30T00:15:31.844Z","schemaVersion":2},"datasetVersion":"2026-08-30T03:17:51.788Z"}