{"record":{"id":"a78b28479bf3545e","repo":"QuantumNous/new-api","slug":"session-expired","errorCode":null,"errorMessage":"Session expired!","messagePattern":"Session expired!","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"web/src/lib/auth-session.ts","lineNumber":419,"sourceCode":"\n  const outcome = await refreshAuthentication()\n  if (outcome.kind === 'authenticated') {\n    return getCommonHeaders()\n  }\n\n  const current = useAuthStore.getState().auth\n  if (\n    current.accessToken &&\n    current.accessExpiresAt &&\n    current.accessExpiresAt > Math.floor(Date.now() / 1000)\n  ) {\n    return getCommonHeaders()\n  }\n\n  if (outcome.kind === 'transient_error') {\n    throw new Error(t('Request failed'), { cause: outcome.error })\n  }\n  throw new Error(t('Session expired!'))\n}\n","sourceCodeStart":401,"sourceCodeEnd":421,"githubUrl":"https://github.com/QuantumNous/new-api/blob/e2c7aa7b102c2075eae2377df3508658d45e88dc/web/src/lib/auth-session.ts#L401-L421","documentation":"Thrown by getFreshAuthHeaders when a token refresh was required and the outcome was NOT a transient error — i.e. the refresh was rejected (expired/invalid session, 401) and no unexpired access token remains in the store. 'Session expired!' is the terminal signal that the user must re-authenticate; retrying will not help.","triggerScenarios":"refreshAuthentication() returns an outcome other than 'authenticated'/'transient_error' (session rejected/revoked server-side) while the stored access token is absent or past accessExpiresAt.","commonSituations":"Server-side session expiry or revocation (logout-all, admin kick, password change); long-lived tab resumed after the refresh token TTL passed; cookie-based refresh credential cleared by browser policy.","solutions":["Redirect the user to the sign-in page when this error is caught — the session is unrecoverable by design.","Verify server session TTL settings versus expected idle time if expiry happens too aggressively.","Check that the refresh credential (cookie/header) is actually sent with the refresh request (withCredentials, same-site cookie config).","If sessions expire unexpectedly fast, inspect backend logs for the session-revocation reason."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try {\n  headers = await getFreshAuthHeaders()\n} catch (error) {\n  if (/Session expired/i.test(error.message)) {\n    // terminal: clear auth store, redirect to /sign-in?redirect=<current route>, no retry\n  }\n}","preventionTips":["Route every authenticated call through getFreshAuthHeaders so expiry is caught in one place","Keep refresh-token TTL aligned with expected user idle time on the server","Always pair the redirect with store cleanup to avoid loops"],"tags":["auth","session-expiry","redirect","terminal"],"backgroundTag":null,"analyzedSha":"e2c7aa7b102c2075eae2377df3508658d45e88dc","analyzedAt":"2026-08-15T10:35:18.111Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}