chatboxai/chatbox · error · Error

MiniMax OAuth state mismatch

Error message

MiniMax OAuth state mismatch

What it means

Thrown in MiniMax startDeviceFlow() when the state echoed in the /oauth/code response does not equal the random state that was sent in the request body. This is a CSRF/response-integrity check: MiniMax is expected to echo the exact state. A mismatch suggests the response was fabricated, replayed from a different session, or the endpoint does not echo state as assumed.

Source

Thrown at src/main/oauth/providers/minimax.ts:121

          state,
        }).toString(),
      })

      if (!response.ok) {
        const text = await response.text()
        throw new Error(`MiniMax authorization failed: ${text}`)
      }

      const payload = (await response.json()) as {
        user_code: string
        verification_uri: string
        expired_in?: number
        interval?: number
        state: string
      }

      if (payload.state !== state) {
        throw new Error('MiniMax OAuth state mismatch')
      }

      pendingUserCode = payload.user_code
      pendingVerifier = verifier
      pendingIntervalMs = toPollingIntervalMs(payload.interval)

      return {
        userCode: payload.user_code,
        verificationUri: payload.verification_uri,
      }
    },

    async waitForToken(signal?: AbortSignal) {
      if (!pendingUserCode || !pendingVerifier) {
        throw new Error('No pending device flow. Call startDeviceFlow first.')
      }

      const userCode = pendingUserCode

View on GitHub (pinned to 81571269ad)

Solutions

  1. Treat a state mismatch as a security failure — do not proceed; abort and restart startDeviceFlow.
  2. Serialize device-flow starts per provider so module-level pendingVerifier/state cannot cross between concurrent calls.
  3. If reproducible, log both sent and received state to determine whether MiniMax stopped echoing it, then adjust the contract deliberately (not by ignoring the check).

Example fix

// before
if (payload.state !== state) {
  throw new Error('MiniMax OAuth state mismatch')
}

// after
if (payload.state !== state) {
  log.error('[OAuth:MiniMax] state mismatch', 'sent=', state, 'recv=', payload.state)
  throw new SecurityError('MiniMax OAuth state mismatch — possible CSRF, retry the login')
}
Defensive patterns

Strategy: try-catch

Try / catch

try {
  return await provider.startDeviceFlow()
} catch (e) {
  if (/state mismatch/i.test(String(e))) {
  // security-relevant: do not retry with same state; restart fresh
  throw new SecurityError('MiniMax state mismatch — possible CSRF; restart login.')
  }
  throw e
}

Prevention

When it happens

Trigger: Two concurrent startDeviceFlow calls sharing module state and crossing responses; a proxy or middleware rewriting or caching the response; MiniMax backend change that no longer echoes the sent state; the response is from a different queued request.

Common situations: Race between two login windows on the same provider; misbehaving CDN cache returning a stale /oauth/code response; backend bug returning an empty or fixed state field.

Related errors


AI-assisted analysis of chatboxai/chatbox@81571269ad (2026-08-12). Data as JSON: /api/errors/e8e908a94fa79a03. Report an issue: GitHub.