mudler/LocalAI · error · Error

HTTP ${response.status}

Error message

HTTP ${response.status}

What it means

Thrown by useChat.js when the legacy MCP SSE streaming POST to the /v1/mcp/chat/completions endpoint returns a non-2xx status. The raw HTTP status/message is only the fallback — extractHttpError(response) is called first to pull a structured error message out of the response body, so the thrown Error usually carries the server's own message (e.g. 'model not found'). This is the chat-modality request path for MCP tool-driven conversations.

Source

Thrown at core/http/react-ui/src/hooks/useChat.js:372

    maxTpsRef.current = 0

    let usage = {}
    const newMessages = [] // Accumulate messages to add to history

    if (activeChat.mcpMode && !hasMcpServers) {
      // Legacy MCP SSE streaming (custom event types from /v1/mcp/chat/completions)
      try {
        const timeoutId = setTimeout(() => controller.abort(), 300000) // 5 min timeout
        const response = await fetch(apiUrl(endpoint), {
          method: 'POST',
          headers: { 'Content-Type': 'application/json' },
          body: JSON.stringify(requestBody),
          signal: controller.signal,
        })
        clearTimeout(timeoutId)

        if (!response.ok) {
          throw new Error(await extractHttpError(response))
        }

        const reader = response.body.pipeThrough(new TextDecoderStream()).getReader()
        let buffer = ''
        let assistantContent = ''
        let reasoningContent = ''
        let hasReasoningFromAPI = false
        let currentToolCalls = []

        while (true) {
          const { value, done } = await reader.read()
          if (done) break

          buffer += value
          const lines = buffer.split('\n')
          buffer = lines.pop() || ''

          for (const line of lines) {

View on GitHub (pinned to 44413a9d06)

Solutions

  1. Read the actual message: the Error text is extracted from the response JSON (extractHttpError), which names the real cause — act on that first
  2. Verify the model exists and is loaded: GET /v1/models in the same UI, and pull/load it if absent
  3. Check auth: if the server runs with an API key, configure it in the UI settings so the request carries it
  4. Confirm the LocalAI version serves /v1/mcp/chat/completions (legacy path) — upgrade or switch to the non-legacy streaming path if not

Example fix

// before
if (!response.ok) {
  throw new Error(await extractHttpError(response))
}

// after — the throw already extracts the server message; surface it fully to the user
catch (err) {
  setError(err.message || `HTTP request failed`)
  addToast(err.message, 'error')
}
Defensive patterns

Strategy: try-catch

Validate before calling

// verify model availability before opening the SSE stream
const models = await modelsApi.listV1()
if (!models.data?.some((m) => m.id === requestBody.model)) throw new Error(`unknown model ${requestBody.model}`)

Try / catch

try {
  const response = await fetch(apiUrl(endpoint), ...)
  if (!response.ok) throw new Error(await extractHttpError(response))
} catch (err) {
  if (err.name === 'AbortError') setError('request timed out')
  else setError(err.message)
}

Prevention

When it happens

Trigger: POSTing a chat completion with MCP tools attached to /v1/mcp/chat/completions where the server rejects it: unknown model name in the request body, model not loaded, missing/invalid auth for the endpoint, or a backend error during tool execution. The 5-minute abort timer (setTimeout controller.abort 300000) can also surface here as an AbortError, but the HTTP error path is specifically a non-ok status.

Common situations: Model name typo or model not pulled/loaded in LocalAI; API key required by the server but not configured in the UI; backend crash mid-request; hitting an older LocalAI build that lacks the /v1/mcp endpoint; CORS/proxy returning 502 in front of LocalAI.

Related errors


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