mudler/LocalAI · error · Error

HTTP ${response.status}

Error message

HTTP ${response.status}

What it means

Fallback error from the streaming fetch helper in utils/api.js used for chat completions: when the response is not ok, it tries to parse the body as JSON and use data.error.message; if the body is not JSON (or has no error.message), the generic 'HTTP <status>' is thrown. This helper always forces stream:true in the body, so it is the shared entry point for all streaming chat/tts/image requests from the React UI.

Source

Thrown at core/http/react-ui/src/utils/api.js:76

  })
}

// SSE streaming for chat completions
export async function streamChat(body, signal) {
  const response = await fetch(apiUrl(API_CONFIG.endpoints.chatCompletions), {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({ ...body, stream: true }),
    signal,
  })

  if (!response.ok) {
    let errorMessage = `HTTP ${response.status}`
    try {
      const data = await response.json()
      if (data?.error?.message) errorMessage = data.error.message
    } catch (_e) { /* not JSON */ }
    throw new Error(errorMessage)
  }

  return response.body
}

// Models API
export const modelsApi = {
  list: (params) => fetchJSON(buildUrl(API_CONFIG.endpoints.models, params)),
  listV1: () => fetchJSON(API_CONFIG.endpoints.modelsList),
  listCapabilities: () => fetchJSON(API_CONFIG.endpoints.modelsCapabilities),
  listAliases: () => fetchJSON(API_CONFIG.endpoints.modelsAliases),
  // variant is optional. Omitting it lets the server auto-select the best
  // build for this host, which is what the listing's auto_variant predicted.
  install: (id, variant) => postJSON(
    variant
      ? `${API_CONFIG.endpoints.installModel(id)}?variant=${encodeURIComponent(variant)}`
      : API_CONFIG.endpoints.installModel(id),
    {}

View on GitHub (pinned to 44413a9d06)

Solutions

  1. Check the status number: 401/403 → configure the API key in UI settings; 404 → fix the API base URL; 502/503 → proxy/upstream health
  2. Reproduce with curl to see the raw body: curl -i -X POST $BASE/v1/chat/completions -H 'Content-Type: application/json' -d '{...}'
  3. Ensure the model exists in GET /v1/models before requesting it
  4. If the server is restarting, wait for /healthz then retry

Example fix

// before
let errorMessage = `HTTP ${response.status}`
try {
  const data = await response.json()
  if (data?.error?.message) errorMessage = data.error.message
} catch (_e) { /* not JSON */ }

// after — also surface text bodies for better diagnosis
let errorMessage = `HTTP ${response.status}`
const text = await response.text()
try {
  const data = JSON.parse(text)
  if (data?.error?.message) errorMessage = data.error.message
} catch (_e) { if (text) errorMessage = text.slice(0, 200) }
Defensive patterns

Strategy: try-catch

Validate before calling

// confirm base URL and auth before streaming
const probe = await fetch(apiUrl('/healthz'))
if (!probe.ok) throw new Error('server unreachable — check API base URL')

Try / catch

try { return await streamFetch(url, body, signal) } catch (e) {
  if (/^HTTP 5/.test(e.message)) throw new Error(`upstream unavailable (${e.message}) — retry shortly`)
  throw e
}

Prevention

When it happens

Trigger: Any streamFetch call (chat completions with stream:true, etc.) receiving a non-2xx whose body is HTML (proxy error page), plain text, or empty — common with 502/503 from reverse proxies, 404 from a wrong API base path, or 401 when the server requires an API key. The JSON parse succeeds only for LocalAI-style {error:{message}} bodies.

Common situations: Reverse proxy (nginx/traefik) in front of LocalAI returning an HTML 502 page; wrong API_PROXY/base URL configured in the UI so /v1/... hits a static file server (404); missing Authorization header on a key-protected instance; LocalAI mid-restart returning connection resets.

Related errors


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