diff --git a/server.py b/server.py index 0ca42d6..bd35eb8 100644 --- a/server.py +++ b/server.py @@ -2032,7 +2032,14 @@ def _transcribe_audio(src: Path, settings: dict, backend: str = "configured") -> headers=hdrs, timeout=60, ) - resp.raise_for_status() + if not resp.ok: + # Extract the real error detail from the response body + try: + body = resp.json() + detail = body.get("detail") or body.get("error") or body.get("message") or str(body) + except Exception: + detail = resp.text[:300].strip() + raise RuntimeError(f"STT backend returned HTTP {resp.status_code}: {detail}") return _transcription_text_from_response(resp), backend diff --git a/static/app.js b/static/app.js index ef8f680..a82badc 100644 --- a/static/app.js +++ b/static/app.js @@ -8544,7 +8544,14 @@ $('s-import-voices-file')?.addEventListener('change', async function () { } else if (evt.type === 'error') { const wrap = assistantBubble.closest('.conv-bubble-wrap'); if (wrap) wrap.remove(); - addErrorBubble(`[${evt.stage?.toUpperCase() || 'ERR'}] ${evt.message}`); + const stage = evt.stage?.toUpperCase() || 'ERR'; + let msg = evt.message || 'Unknown error'; + // Surface the actual server error detail, not the raw HTTP noise + const detailMatch = msg.match(/HTTP \d+:\s*(.+)/s); + if (detailMatch) msg = detailMatch[1].trim(); + // Truncate very long stack traces + if (msg.length > 300) msg = msg.slice(0, 300) + '…'; + addErrorBubble(`[${stage}] ${msg}`); addHistoryItem(turnN, Date.now() - t0, false); if (micStatus) micStatus.textContent = 'Error — ready'; }