HKUDS/DeepTutor · error · VoiceProviderError
OpenRouter chat audio returned empty audio.
Error message
OpenRouter chat audio returned empty audio.
What it means
The OpenRouter fallback successfully decoded base64 audio but the decoded bytes are empty (zero-length). The adapter refuses to return empty audio and raises VoiceProviderError.
Source
Thrown at deeptutor/services/voice/adapters/openai_compat.py:251
except httpx.HTTPError as exc:
detail = str(exc) or exc.__class__.__name__
raise VoiceProviderError(f"TTS request error: {detail}") from exc
except VoiceProviderHTTPError as exc:
raise VoiceProviderError(
f"{exc}; original /audio/speech error: {original_error}"
) from exc
if not audio_chunks:
raise VoiceProviderError(
"OpenRouter chat audio returned no audio chunks; "
f"original /audio/speech error: {original_error}"
)
try:
audio = base64.b64decode("".join(audio_chunks))
except binascii.Error as exc:
raise VoiceProviderError("OpenRouter chat audio returned invalid base64.") from exc
if not audio:
raise VoiceProviderError("OpenRouter chat audio returned empty audio.")
content_type = _FORMAT_CONTENT_TYPES.get(audio_format, "application/octet-stream")
return audio, content_type
@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])
returnView on GitHub (pinned to 3e82f13042)
Solutions
- Retry with a shorter, clearly speakable text input
- Switch to an audio-capable model or a native TTS provider
- Check the original /audio/speech error (not included here) for the underlying provider issue
- Enable debug logging to see the raw chunks received
Defensive patterns
Strategy: fallback
Try / catch
try:
audio, ct = await adapter.synthesize(text, config)
except VoiceProviderError as exc:
if "empty audio" in str(exc):
return await native_tts.synthesize(text, native_config)
raise Prevention
- Keep a secondary TTS provider configured for automatic failover
- Smoke-test new models with short utterances before production use
When it happens
Trigger: The SSE stream contained one or more chunks that decode to zero bytes — e.g. a single empty-string chunk, or padding-only base64.
Common situations: Model acknowledged the audio request but produced an empty payload (often when the prompt elicits no spoken content, or the modulation is ignored). Usually paired with a prior /audio/speech failure.
Related errors
- OpenRouter chat audio returned no audio chunks; original /au
- No endpoint URL configured for this provider.
- {exc}{hint}
- TTS provider returned empty audio.
- TTS request error: {detail}
AI-assisted analysis of HKUDS/DeepTutor@3e82f13042 (2026-08-27).
Data as JSON: /api/errors/306ba1c6ac0854b9.
Report an issue: GitHub.