mudler/LocalAI · error · Error
HTTP ${response.status}
Error message
HTTP ${response.status} What it means
In the legacy static-UI talk page (core/http/static/talk.js), the browser POSTs its WebRTC SDP offer to 'v1/realtime/calls' to have the server negotiate a realtime voice session. On a non-ok response it tries to read err.error from the JSON body and falls back to 'HTTP <status>'. Failure here means the realtime voice call could not be established at all — no answer SDP comes back.
Source
Thrown at core/http/static/talk.js:348
};
// Timeout after 5s
setTimeout(resolve, 5000);
}
});
// Send offer to server
const response = await fetch('v1/realtime/calls', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
sdp: pc.localDescription.sdp,
model: model,
}),
});
if (!response.ok) {
const err = await response.json().catch(() => ({ error: 'Unknown error' }));
throw new Error(err.error || `HTTP ${response.status}`);
}
const data = await response.json();
// Set remote description (server's answer)
await pc.setRemoteDescription({
type: 'answer',
sdp: data.sdp,
});
console.log('WebRTC connection established, session:', data.session_id);
} catch (err) {
console.error('Connection failed:', err);
hasError = true;
setStatus('error', 'Connection failed: ' + err.message);
disconnect();
}
}View on GitHub (pinned to 44413a9d06)
Solutions
- Check the JSON error message first (err.error) — the server usually names the missing capability or model
- Verify the LocalAI build serves POST /v1/realtime/calls (curl -i -X POST with a dummy SDP) and rebuild with the realtime backend if not
- Use a realtime-capable model and confirm it is loaded via /v1/models
- Ensure the talk page is served from the same origin (or the proxy forwards v1/realtime/* correctly) and auth headers are present
Example fix
// before
const response = await fetch('v1/realtime/calls', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ sdp: pc.localDescription.sdp, model }) });
// after — absolute URL + auth + richer fallback
const response = await fetch(`${window.location.origin}/v1/realtime/calls`, {
method: 'POST',
headers: { 'Content-Type': 'application/json', ...(apiKey ? { Authorization: `Bearer ${apiKey}` } : {}) },
body: JSON.stringify({ sdp: pc.localDescription.sdp, model }),
}); Defensive patterns
Strategy: try-catch
Validate before calling
// probe the realtime endpoint before offering the talk button
const probe = await fetch('v1/realtime/calls', { method: 'OPTIONS' }).catch(() => null)
if (!probe || probe.status === 404) showRealtimeUnavailableNotice() Try / catch
try { const data = await postSdpOffer(pc, model) } catch (err) {
const detail = err.message.replace(/^HTTP (\d+)$/, 'server rejected the call ($1)')
showMicStatus(detail)
pc.close()
} Prevention
- Serve the talk page from the same origin as the API, or proxy v1/realtime/* explicitly
- Confirm the server build includes the realtime backend before exposing voice UI
- Send the API key with the offer POST on protected instances
- Close the PeerConnection in the catch to avoid leaked ICE agents
When it happens
Trigger: POSTing the SDP offer when the realtime endpoint is not served (older LocalAI, realtime backend not built/enabled), the requested model lacks realtime/audio capability (400 with an error message), server-side WebRTC stack failure, or auth rejection (401/403) on the endpoint. The relative URL also breaks if the page is served from a different origin without a proxy rewrite.
Common situations: LocalAI build without the realtime backend; model name not matching an audio-realtime model in config; API key required but the talk page not sending it; reverse proxy stripping or misrouting v1/realtime/*;TURN/STUN unrelated — this error is pure HTTP, before ICE.
Related errors
- HTTP ${response.status}
- HTTP ${response.status}
- HTTP ${r.status}
- status: HTTP ${statusRes.status}
- HTTP ${response.status}
AI-assisted analysis of mudler/LocalAI@44413a9d06 (2026-08-15).
Data as JSON: /api/errors/0978686425eb63cb.
Report an issue: GitHub.