mastra-ai/mastra · error

State mismatch

Error message

State mismatch

What it means

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.

Source

Thrown at mastracode/sdk/src/auth/providers/openai-codex.ts:646

          manualError = err instanceof Error ? err : new Error(String(err));
          server.cancelWait();
        });

      const result = await server.waitForCode();

      // If manual input was cancelled, throw that error
      if (manualError) {
        throw manualError;
      }

      if (result?.code) {
        // Browser callback won
        code = result.code;
      } else if (manualCode) {
        // Manual input won (or callback timed out and user had entered code)
        const parsed = parseAuthorizationInput(manualCode);
        if (parsed.state && parsed.state !== state) {
          throw new Error('State mismatch');
        }
        code = parsed.code;
      }

      // If still no code, wait for manual promise to complete and try that
      if (!code) {
        await manualPromise;
        if (manualError) {
          throw manualError;
        }
        if (manualCode) {
          const parsed = parseAuthorizationInput(manualCode);
          if (parsed.state && parsed.state !== state) {
            throw new Error('State mismatch');
          }
          code = parsed.code;
        }
      }

View on GitHub (pinned to 75dd419e61)

Solutions

  1. Re-run the login and paste the redirect URL from the browser tab opened by THIS run (check the state query param matches).
  2. Close stale browser tabs from earlier login attempts before retrying.
  3. If multiple logins run concurrently, serialize them or use separate sessions.
  4. If you control the flow, log the expected state so users can verify before pasting.

Example fix

// before: pasting an old URL
const input = 'http://localhost:1455/auth/callback?code=OLD&state=OLD_STATE';
await loginOpenAICodex({ onPrompt: () => input });

// after: use the URL from the current attempt
const currentUrl = 'http://localhost:1455/auth/callback?code=NEW&state=CURRENT_STATE';
await loginOpenAICodex({ onPrompt: () => currentUrl });
Defensive patterns

Strategy: validation

Validate before calling

function statesMatch(pastedUrl: string, expectedState: string): boolean {
  const state = new URL(pastedUrl).searchParams.get('state');
  return !state || state === expectedState;
}
// check before passing input to the login call/prompt

Try / catch

try {
  await loginOpenAICodex({ onPrompt });
} catch (e) {
  if (e.message === 'State mismatch') {
    console.error('Pasted URL is from a different login session. Restart and use the current URL.');
  } else throw e;
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


AI-assisted analysis of mastra-ai/mastra@75dd419e61 (2026-08-30). Data as JSON: /api/errors/da8b6edf782228f6. Report an issue: GitHub.