{"record":{"id":"0978686425eb63cb","repo":"mudler/LocalAI","slug":"http-response-status-097868","errorCode":null,"errorMessage":"HTTP ${response.status}","messagePattern":"HTTP \\$\\{response\\.status\\}","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"core/http/static/talk.js","lineNumber":348,"sourceCode":"        };\n        // Timeout after 5s\n        setTimeout(resolve, 5000);\n      }\n    });\n\n    // Send offer to server\n    const response = await fetch('v1/realtime/calls', {\n      method: 'POST',\n      headers: { 'Content-Type': 'application/json' },\n      body: JSON.stringify({\n        sdp: pc.localDescription.sdp,\n        model: model,\n      }),\n    });\n\n    if (!response.ok) {\n      const err = await response.json().catch(() => ({ error: 'Unknown error' }));\n      throw new Error(err.error || `HTTP ${response.status}`);\n    }\n\n    const data = await response.json();\n\n    // Set remote description (server's answer)\n    await pc.setRemoteDescription({\n      type: 'answer',\n      sdp: data.sdp,\n    });\n\n    console.log('WebRTC connection established, session:', data.session_id);\n  } catch (err) {\n    console.error('Connection failed:', err);\n    hasError = true;\n    setStatus('error', 'Connection failed: ' + err.message);\n    disconnect();\n  }\n}","sourceCodeStart":330,"sourceCodeEnd":366,"githubUrl":"https://github.com/mudler/LocalAI/blob/44413a9d06bf5bc52ce088ba8ca74e5a2e8bee26/core/http/static/talk.js#L330-L366","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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"],"exampleFix":"// before\nconst response = await fetch('v1/realtime/calls', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ sdp: pc.localDescription.sdp, model }) });\n\n// after — absolute URL + auth + richer fallback\nconst response = await fetch(`${window.location.origin}/v1/realtime/calls`, {\n  method: 'POST',\n  headers: { 'Content-Type': 'application/json', ...(apiKey ? { Authorization: `Bearer ${apiKey}` } : {}) },\n  body: JSON.stringify({ sdp: pc.localDescription.sdp, model }),\n});","handlingStrategy":"try-catch","validationCode":"// probe the realtime endpoint before offering the talk button\nconst probe = await fetch('v1/realtime/calls', { method: 'OPTIONS' }).catch(() => null)\nif (!probe || probe.status === 404) showRealtimeUnavailableNotice()","typeGuard":null,"tryCatchPattern":"try { const data = await postSdpOffer(pc, model) } catch (err) {\n  const detail = err.message.replace(/^HTTP (\\d+)$/, 'server rejected the call ($1)')\n  showMicStatus(detail)\n  pc.close()\n}","preventionTips":["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"],"tags":["http","webrtc","realtime","voice","legacy-ui"],"backgroundTag":null,"analyzedSha":"44413a9d06bf5bc52ce088ba8ca74e5a2e8bee26","analyzedAt":"2026-08-15T10:13:50.291Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}