{"record":{"id":"6973ae67ff9755ac","repo":"mudler/LocalAI","slug":"http-res-status","errorCode":null,"errorMessage":"HTTP ${res.status}","messagePattern":"HTTP \\$\\{res\\.status\\}","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"core/http/react-ui/src/pages/Usage.jsx","lineNumber":660,"sourceCode":"  const [pricing, setPricingState] = useState(loadPricing)\n  const [showPricing, setShowPricing] = useState(false)\n  const setPricing = (p) => { setPricingState(p); savePricing(p) }\n  const costEnabled = pricingEnabled(pricing)\n\n  const fetchUsage = useCallback(async () => {\n    setLoading(true)\n    try {\n      // /api/usage works in no-auth single-user mode (returns the synthetic\n      // local user's usage). /api/auth/usage is the legacy auth-required\n      // path; we keep using it when auth is on so /api/auth/quota and\n      // friends remain consistent.\n      const userUsageURL = authEnabled ? '/api/auth/usage' : '/api/usage'\n      const usagePromise = fetch(apiUrl(`${userUsageURL}?period=${period}`))\n      const quotaPromise = authEnabled ? fetch(apiUrl('/api/auth/quota')) : Promise.resolve(null)\n\n      const [res, quotaRes] = await Promise.all([usagePromise, quotaPromise])\n\n      if (!res.ok) throw new Error(`HTTP ${res.status}`)\n      const data = await res.json()\n      setUsage(data.usage || [])\n      setTotals(data.totals || {})\n\n      if (quotaRes && quotaRes.ok) {\n        const quotaData = await quotaRes.json()\n        setQuotas(quotaData.quotas || [])\n      }\n\n      if (isAdmin) {\n        // /api/usage/all serves the cluster-wide view in both modes.\n        // The synthetic local user has Role: admin, so single-user mode\n        // gets the admin-style cross-user table (which collapses to one\n        // row, but keeps the UI shape consistent).\n        const adminURL = authEnabled ? '/api/auth/admin/usage' : '/api/usage/all'\n        const adminRes = await fetch(apiUrl(`${adminURL}?period=${period}`))\n        if (adminRes.ok) {\n          const adminData = await adminRes.json()","sourceCodeStart":642,"sourceCodeEnd":678,"githubUrl":"https://github.com/mudler/LocalAI/blob/44413a9d06bf5bc52ce088ba8ca74e5a2e8bee26/core/http/react-ui/src/pages/Usage.jsx#L642-L678","documentation":"Thrown by the Usage page loader when the usage fetch (GET /api/auth/usage?period=<period> when auth is enabled, or GET /api/usage?period=<period> in single-user mode) returns non-OK. The quota fetch (/api/auth/quota, auth mode only) is optional and failures are ignored; the cluster-wide /api/usage/all (admin only) is separate. Only the per-user usage response is fatal.","triggerScenarios":"Auth enabled with an expired token hitting /api/auth/usage (401); auth disabled but the server requiring auth anyway (401/403 on /api/usage); an invalid period query parameter (400); server-side usage store error (500).","commonSituations":"Long-lived tab with a stale auth state where authEnabled was computed at mount; mismatch between the client's belief about auth and the server's config after a settings change; proxy stripping the period query.","solutions":["Determine actual auth mode (GET /api/auth/config or equivalent) and verify the same endpoint the page used","If 401, refresh auth/login and reload the page so authEnabled is recomputed","If 400, check the period value sent (network tab) is one the server accepts","If 5xx, check server logs for the usage handler"],"exampleFix":"// before\nif (!res.ok) throw new Error(`HTTP ${res.status}`)\n\n// after: give an actionable hint for the common auth-expiry case\nif (!res.ok) {\n  throw new Error(res.status === 401\n    ? 'HTTP 401 — session expired; reload to re-authenticate'\n    : `HTTP ${res.status}`)\n}","handlingStrategy":"try-catch","validationCode":"// Resolve the correct base path before loading, mirroring the page's auth-mode logic\nfunction usageEndpoint(authEnabled) {\n  return authEnabled ? '/api/auth/usage' : '/api/usage'\n}","typeGuard":null,"tryCatchPattern":"try {\n  const [res, quotaRes] = await Promise.all([usagePromise, quotaPromise])\n  if (!res.ok) {\n    if (res.status === 401 && authEnabled) { await reauthenticate(); return load() } // session expired: fix and recurse once\n    throw new Error(`HTTP ${res.status}`)\n  }\n  // ...\n} catch (err) {\n  setError(err.message)\n}","preventionTips":["Recompute authEnabled on each load rather than caching it across sessions","Handle 401 by refreshing auth once instead of surfacing a raw HTTP error","Keep the quota fetch optional (as written) so quota failures never break the usage view"],"tags":["http","usage","auth","react-ui"],"backgroundTag":null,"analyzedSha":"44413a9d06bf5bc52ce088ba8ca74e5a2e8bee26","analyzedAt":"2026-08-15T10:13:50.291Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}