{"record":{"id":"7470730d90b1637a","repo":"QuantumNous/new-api","slug":"request-failed","errorCode":null,"errorMessage":"Request failed","messagePattern":"Request failed","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"web/src/lib/auth-session.ts","lineNumber":417,"sourceCode":"    return getCommonHeaders()\n  }\n\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":399,"sourceCodeEnd":421,"githubUrl":"https://github.com/QuantumNous/new-api/blob/e2c7aa7b102c2075eae2377df3508658d45e88dc/web/src/lib/auth-session.ts#L399-L421","documentation":"Thrown by getFreshAuthHeaders when a token refresh was needed (access token missing or expiring within 60s), the refresh attempt ended as outcome.kind 'transient_error', and no still-valid token exists in the store. 'Request failed' (i18n key) means the refresh could not complete due to a network/transport problem, not an auth rejection; the original error is attached as { cause }.","triggerScenarios":"refreshAuthentication() returns {kind:'transient_error'} — offline, DNS failure, connection reset, 5xx from the session endpoint — while auth.accessExpiresAt is already past, so no cached token can serve the request.","commonSituations":"Brief network drop or backend restart exactly when the access token expired; mobile/flaky connections; proxy timeouts on the refresh endpoint during deploys.","solutions":["Retry the originating request after connectivity returns — inspect error.cause to confirm it is a network-level failure (TypeError: Failed to fetch, ECONNRESET-equivalent).","Check whether the backend session/refresh endpoint is up (curl it) and whether a deploy was in progress.","Add bounded retry with backoff around getFreshAuthHeaders for transient_error outcomes so momentary outages self-heal.","If it persists, capture outcome.error details — a misclassified non-transient failure masquerading as transient is a bug in refreshAuthentication's classification."],"exampleFix":"// caller-side bounded retry for transient refresh failures\nasync function withFreshHeaders(retries = 2): Promise<Record<string, string>> {\n  try {\n    return await getFreshAuthHeaders()\n  } catch (error) {\n    if (retries > 0 && error.cause !== undefined && navigator.onLine) {\n      await new Promise((r) => setTimeout(r, 1000))\n      return withFreshHeaders(retries - 1)\n    }\n    throw error\n  }\n}","handlingStrategy":"retry","validationCode":"if (!navigator.onLine) {\n  // skip the request now; queue it until connectivity returns instead of eating a transient_error\n}","typeGuard":null,"tryCatchPattern":"try {\n  headers = await getFreshAuthHeaders()\n} catch (error) {\n  if (/Request failed/i.test(error.message)) {\n    // inspect error.cause; retry with backoff when offline/5xx, abort on hard failures\n  }\n}","preventionTips":["Wrap getFreshAuthHeaders in a bounded retry (2 attempts, exponential backoff) for transient outcomes","Refresh tokens proactively (the 60s refreshBefore window) so requests rarely need a live refresh to succeed"],"tags":["auth","refresh","network","retry"],"backgroundTag":null,"analyzedSha":"e2c7aa7b102c2075eae2377df3508658d45e88dc","analyzedAt":"2026-08-15T10:35:18.111Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}