HKUDS/DeepTutor · error · VoiceProviderError
OpenRouter chat audio error: {message}
Error message
OpenRouter chat audio error: {message} What it means
_collect_audio_line parses each SSE line from the OpenRouter chat stream; if the decoded JSON chunk contains an "error" object, it extracts message/code and raises VoiceProviderError("OpenRouter chat audio error: {message}"). This surfaces mid-stream errors that arrive with HTTP 200.
Source
Thrown at deeptutor/services/voice/adapters/openai_compat.py:273
@staticmethod
def _collect_audio_line(line: str, audio_chunks: list[str]) -> None:
if not line:
return
raw = line.strip()
if not raw.startswith("data:"):
return
data = raw[len("data:") :].strip()
if not data or data == "[DONE]":
return
try:
chunk = json.loads(data)
except json.JSONDecodeError:
logger.debug("Ignoring malformed OpenRouter SSE line: %s", data[:160])
return
error = chunk.get("error")
if isinstance(error, dict):
message = error.get("message") or error.get("code") or "unknown error"
raise VoiceProviderError(f"OpenRouter chat audio error: {message}")
choices = chunk.get("choices")
if not isinstance(choices, list):
return
for choice in choices:
if not isinstance(choice, dict):
continue
delta = choice.get("delta") or {}
if not isinstance(delta, dict):
continue
audio = delta.get("audio") or {}
if isinstance(audio, dict) and isinstance(audio.get("data"), str):
audio_chunks.append(audio["data"])
class OpenAICompatSTTAdapter(BaseSTTAdapter):
"""POST ``{base}/audio/transcriptions``.
Multipart ``file`` upload by default; OpenRouter uses a base64-JSON bodyView on GitHub (pinned to 3e82f13042)
Solutions
- Act on the embedded message: top up credits (402-style), fix the model slug, or adjust content that triggered moderation
- Retry once for transient credit/auth propagation delays
- Verify the model exists and supports audio on OpenRouter's model listing
- If errors persist, disable the chat fallback and use a native TTS provider
Defensive patterns
Strategy: try-catch
Try / catch
try:
audio, ct = await adapter.synthesize(text, config)
except VoiceProviderError as exc:
if "chat audio error" in str(exc):
log.error("OpenRouter stream error: %s", exc) # credits/model/moderation
raise Prevention
- Monitor OpenRouter credit balance with alerts
- Pin known-good model slugs; verify them after upgrades
- Handle in-stream errors distinctly from HTTP-status errors
When it happens
Trigger: The chat/completions stream starts with HTTP 200 but emits an error event — e.g. invalid model, insufficient credits, or content-policy rejection delivered as an SSE error payload.
Common situations: OpenRouter credit exhaustion mid-request, deprecated/renamed model slug, or moderation blocks — all delivered as in-stream error objects instead of HTTP status codes.
Related errors
- OpenRouter chat audio returned no audio chunks; original /au
- No endpoint URL configured for this provider.
- {exc}{hint}
- TTS request error: {detail}
- {exc}; original /audio/speech error: {original_error}
AI-assisted analysis of HKUDS/DeepTutor@3e82f13042 (2026-08-27).
Data as JSON: /api/errors/7f93ce8ac971b228.
Report an issue: GitHub.