{"record":{"id":"4492f25aab7994e6","repo":"QuantumNous/new-api","slug":"authentication-rotation-session-mismatch","errorCode":null,"errorMessage":"Authentication rotation session mismatch","messagePattern":"Authentication rotation session mismatch","errorType":"exception","errorClass":"AuthRotationError","httpStatus":null,"severity":"error","filePath":"web/src/lib/auth-session.ts","lineNumber":170,"sourceCode":"  const previousSID = useAuthStore.getState().auth.session?.sid\n  authEpoch += 1\n  useAuthStore.getState().auth.setBundle(bundle)\n  if (synchronizeTabs && previousSID !== bundle.session.sid) {\n    publishAuthSessionEvent('authenticated', bundle.session.sid)\n  }\n}\n\nexport function applyAuthRotation(value: unknown): void {\n  if (!isAuthTokenRotation(value)) {\n    throw new AuthRotationError('Invalid authentication rotation response')\n  }\n\n  const auth = useAuthStore.getState().auth\n  if (!auth.user || !auth.session) {\n    throw new AuthRotationError('Authentication rotation has no active session')\n  }\n  if (value.session.sid !== auth.session.sid) {\n    throw new AuthRotationError('Authentication rotation session mismatch')\n  }\n\n  applyAuthBundle(\n    {\n      access_token: value.access_token,\n      token_type: value.token_type,\n      access_expires_at: value.access_expires_at,\n      session: value.session,\n      user: auth.user,\n    },\n    false\n  )\n}\n\nexport function clearAuthentication(\n  synchronizeTabs = true,\n  bootstrapState: AuthBootstrapState = 'complete'\n): void {","sourceCodeStart":152,"sourceCodeEnd":188,"githubUrl":"https://github.com/QuantumNous/new-api/blob/e2c7aa7b102c2075eae2377df3508658d45e88dc/web/src/lib/auth-session.ts#L152-L188","documentation":"Thrown by applyAuthRotation when the rotation payload's session.sid differs from the sid currently in the auth store. Sessions are identified by sid; a mismatch means the response belongs to a different session (new login elsewhere, session re-created by the server, or cross-tab drift), and applying it would silently merge two identities.","triggerScenarios":"Rotation endpoint returns credentials bound to a different sid than auth.session.sid: the same account re-authenticated in another tab creating a new session, server-side session regeneration, or a duplicated/stale refresh response replayed after re-login.","commonSituations":"Two tabs sharing localStorage where one re-logs-in and changes the session while the other's rotation is in flight; backend regenerating sessions on privilege change; a queued retry of an old refresh response after the store already holds a new session.","solutions":["If the store's sid is stale (another tab logged in fresh), the cross-tab authenticated event should have replaced the bundle — verify publishAuthSessionEvent handling and tab synchronization.","Tag refresh requests with the current sid and have the server reject rotations for superseded sessions, so mismatches become explicit 401s instead of client-side throws.","On this error, force a full re-bootstrap (bootstrapAuthentication) or redirect to sign-in; do not retry the same rotation blindly."],"exampleFix":null,"handlingStrategy":"validation","validationCode":"const currentSid = useAuthStore.getState().auth.session?.sid\nif (value.session.sid !== currentSid) {\n  // stale or foreign session: re-bootstrap instead of applying\n  await bootstrapAuthentication()\n  return\n}","typeGuard":null,"tryCatchPattern":"try {\n  applyAuthRotation(value)\n} catch (error) {\n  if (error instanceof AuthRotationError && /session mismatch/i.test(error.message)) {\n    await bootstrapAuthentication() // adopt whichever session is authoritative\n    return\n  }\n  throw error\n}","preventionTips":["Echo the current sid in the refresh request so the server rejects rotations for superseded sessions","Ensure cross-tab authenticated events update the store before late rotation responses land"],"tags":["auth","token-rotation","session-mismatch","multi-tab"],"backgroundTag":null,"analyzedSha":"e2c7aa7b102c2075eae2377df3508658d45e88dc","analyzedAt":"2026-08-15T10:35:18.111Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}