{"record":{"id":"e4b9c24a51897be6","repo":"QuantumNous/new-api","slug":"invalid-authentication-rotation-response","errorCode":null,"errorMessage":"Invalid authentication rotation response","messagePattern":"Invalid authentication rotation response","errorType":"exception","errorClass":"AuthRotationError","httpStatus":null,"severity":"error","filePath":"web/src/lib/auth-session.ts","lineNumber":162,"sourceCode":"    value.session.current\n  )\n}\n\nexport function applyAuthBundle(\n  bundle: AuthBundle,\n  synchronizeTabs = true\n): void {\n  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    },","sourceCodeStart":144,"sourceCodeEnd":180,"githubUrl":"https://github.com/QuantumNous/new-api/blob/e2c7aa7b102c2075eae2377df3508658d45e88dc/web/src/lib/auth-session.ts#L144-L180","documentation":"Thrown by applyAuthRotation in the auth session module when a payload delivered to rotate the access token fails the isAuthTokenRotation structural check (missing/malformed access_token, session, expiry, or token_type fields). It guards the store against installing a corrupt rotation payload that would break every subsequent authenticated request.","triggerScenarios":"An auth rotation response (token refresh path) arrives that is not shaped like an AuthTokenRotation: missing access_token, missing session.sid, non-numeric access_expires_at, or the payload is null/an error envelope that leaked into the rotation channel.","commonSituations":"Backend version change altering the rotation response shape; a proxy returning an HTML error page parsed as JSON; interceptor accidentally forwarding an error body to applyAuthRotation; race where a logout response is mistaken for rotation.","solutions":["Log the actual value passed to applyAuthRotation (never in production output) and diff it against the expected fields: access_token, token_type, access_expires_at, session.sid.","Check the backend rotation endpoint's response schema and align isAuthTokenRotation with it after any backend upgrade.","Ensure the fetch wrapper rejects non-JSON responses (check content-type) before the rotation path sees them.","After the throw, force re-authentication — the rotation is skipped and the old token remains, so redirect to sign-in rather than retrying in a loop."],"exampleFix":null,"handlingStrategy":"type-guard","validationCode":null,"typeGuard":"// isAuthTokenRotation already exists; reuse it before calling applyAuthRotation\nimport { isAuthTokenRotation } from '@/lib/auth-session'\nif (!isAuthTokenRotation(payload)) {\n  // force re-login instead of letting AuthRotationError propagate\n}","tryCatchPattern":"try {\n  applyAuthRotation(payload)\n} catch (error) {\n  if (error instanceof AuthRotationError) {\n    // clear auth state and redirect to /sign-in; do not retry with the same payload\n  }\n  throw error\n}","preventionTips":["Pin the rotation response contract with a schema test against a backend fixture","Reject non-JSON content-type responses in the fetch wrapper before they reach rotation handling","Version the rotation payload (field on the envelope) so contract drift is detectable"],"tags":["auth","token-rotation","type-guard","session"],"backgroundTag":null,"analyzedSha":"e2c7aa7b102c2075eae2377df3508658d45e88dc","analyzedAt":"2026-08-15T10:35:18.111Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}