mudler/LocalAI · error · Error

HTTP ${res.status}

Error message

HTTP ${res.status}

What it means

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.

Source

Thrown at core/http/react-ui/src/pages/Usage.jsx:660

  const [pricing, setPricingState] = useState(loadPricing)
  const [showPricing, setShowPricing] = useState(false)
  const setPricing = (p) => { setPricingState(p); savePricing(p) }
  const costEnabled = pricingEnabled(pricing)

  const fetchUsage = useCallback(async () => {
    setLoading(true)
    try {
      // /api/usage works in no-auth single-user mode (returns the synthetic
      // local user's usage). /api/auth/usage is the legacy auth-required
      // path; we keep using it when auth is on so /api/auth/quota and
      // friends remain consistent.
      const userUsageURL = authEnabled ? '/api/auth/usage' : '/api/usage'
      const usagePromise = fetch(apiUrl(`${userUsageURL}?period=${period}`))
      const quotaPromise = authEnabled ? fetch(apiUrl('/api/auth/quota')) : Promise.resolve(null)

      const [res, quotaRes] = await Promise.all([usagePromise, quotaPromise])

      if (!res.ok) throw new Error(`HTTP ${res.status}`)
      const data = await res.json()
      setUsage(data.usage || [])
      setTotals(data.totals || {})

      if (quotaRes && quotaRes.ok) {
        const quotaData = await quotaRes.json()
        setQuotas(quotaData.quotas || [])
      }

      if (isAdmin) {
        // /api/usage/all serves the cluster-wide view in both modes.
        // The synthetic local user has Role: admin, so single-user mode
        // gets the admin-style cross-user table (which collapses to one
        // row, but keeps the UI shape consistent).
        const adminURL = authEnabled ? '/api/auth/admin/usage' : '/api/usage/all'
        const adminRes = await fetch(apiUrl(`${adminURL}?period=${period}`))
        if (adminRes.ok) {
          const adminData = await adminRes.json()

View on GitHub (pinned to 44413a9d06)

Solutions

  1. Determine actual auth mode (GET /api/auth/config or equivalent) and verify the same endpoint the page used
  2. If 401, refresh auth/login and reload the page so authEnabled is recomputed
  3. If 400, check the period value sent (network tab) is one the server accepts
  4. If 5xx, check server logs for the usage handler

Example fix

// before
if (!res.ok) throw new Error(`HTTP ${res.status}`)

// after: give an actionable hint for the common auth-expiry case
if (!res.ok) {
  throw new Error(res.status === 401
    ? 'HTTP 401 — session expired; reload to re-authenticate'
    : `HTTP ${res.status}`)
}
Defensive patterns

Strategy: try-catch

Validate before calling

// Resolve the correct base path before loading, mirroring the page's auth-mode logic
function usageEndpoint(authEnabled) {
  return authEnabled ? '/api/auth/usage' : '/api/usage'
}

Try / catch

try {
  const [res, quotaRes] = await Promise.all([usagePromise, quotaPromise])
  if (!res.ok) {
    if (res.status === 401 && authEnabled) { await reauthenticate(); return load() } // session expired: fix and recurse once
    throw new Error(`HTTP ${res.status}`)
  }
  // ...
} catch (err) {
  setError(err.message)
}

Prevention

When it happens

Trigger: 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).

Common situations: 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.

Related errors


AI-assisted analysis of mudler/LocalAI@44413a9d06 (2026-08-15). Data as JSON: /api/errors/6973ae67ff9755ac. Report an issue: GitHub.