HKUDS/DeepTutor · error · VoiceProviderError

TTS provider returned empty audio.

Error message

TTS provider returned empty audio.

What it means

After a successful HTTP response from /audio/speech, the adapter checks resp.content; an empty body means the provider claimed success but returned zero audio bytes, so a VoiceProviderError is raised rather than returning invalid audio.

Source

Thrown at deeptutor/services/voice/adapters/openai_compat.py:157

            config.voice,
            response_format,
            len(text),
        )
        try:
            async with httpx.AsyncClient(timeout=config.request_timeout) as client:
                resp = await client.post(url, headers=headers, json=payload)
        except httpx.HTTPError as exc:
            raise VoiceProviderError(f"TTS request error: {exc}") from exc
        try:
            _raise_for_provider(resp, "TTS synthesis")
        except VoiceProviderHTTPError as exc:
            hint = _openrouter_tts_hint(config)
            if hint:
                raise VoiceProviderError(f"{exc}{hint}") from exc
            raise
        audio = resp.content
        if not audio:
            raise VoiceProviderError("TTS provider returned empty audio.")
        content_type = resp.headers.get("content-type") or _FORMAT_CONTENT_TYPES.get(
            response_format, "application/octet-stream"
        )
        # Some gateways return JSON content-type with audio; trust the format map.
        if "json" in content_type:
            content_type = _FORMAT_CONTENT_TYPES.get(response_format, "audio/mpeg")
        return audio, content_type


class OpenRouterTTSAdapter(BaseTTSAdapter):
    """OpenRouter TTS with fallback for streaming chat-audio models.

    OpenRouter documents both a dedicated ``/audio/speech`` endpoint for TTS
    models and audio output through ``/chat/completions`` for models that expose
    the ``audio`` output modality. Try the dedicated endpoint first, then fall
    back to chat audio for configs pointed at audio-output chat models.
    """

View on GitHub (pinned to 3e82f13042)

Solutions

  1. Retry once — some providers intermittently return empty bodies
  2. Try a different response_format (e.g. mp3 vs wav) or a different voice/model
  3. If self-hosted, check server logs; if proxied, bypass the proxy to compare
  4. Report to the provider if it consistently returns 200 with empty content
Defensive patterns

Strategy: retry

Try / catch

try:
    audio, ct = await adapter.synthesize(text, config)
except VoiceProviderError as exc:
    if "empty audio" in str(exc) and attempt < MAX:
        continue  # retry — intermittently empty bodies
    raise

Prevention

When it happens

Trigger: Provider returns 200 with an empty body — seen with some gateways/proxies that strip binary responses, misconfigured self-hosted TTS, or models that silently produce nothing.

Common situations: A reverse proxy buffering/corrupting binary output, a provider bug for a specific voice/format combination, or an unsupported response_format that the gateway ignores.

Related errors


AI-assisted analysis of HKUDS/DeepTutor@3e82f13042 (2026-08-27). Data as JSON: /api/errors/d3c84ed29dfc72b5. Report an issue: GitHub.