HKUDS/DeepTutor · error · VoiceProviderError
{exc}{hint}
Error message
{exc}{hint} What it means
After the provider returned an HTTP >= 400 for TTS synthesis, _raise_for_provider raised VoiceProviderHTTPError; if the config looks like OpenRouter (per _openrouter_tts_hint), the adapter re-raises as VoiceProviderError with an appended hint explaining OpenRouter's audio support. The message combines the provider error detail and the hint.
Source
Thrown at deeptutor/services/voice/adapters/openai_compat.py:153
logger.debug(
"TTS synthesize url=%s model=%s voice=%s fmt=%s chars=%d",
url,
config.model,
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 exposeView on GitHub (pinned to 3e82f13042)
Solutions
- Read the appended hint — it usually says to use an audio-capable model or the chat fallback
- Switch the TTS model to one that supports /audio/speech on OpenRouter
- Verify the API key and account credits if the status is 401/402
- If the fallback should have run, ensure the adapter used is OpenRouterTTSAdapter so _synthesize_chat_audio is attempted
Example fix
// before cfg = TTSConfig(model="gpt-4o-mini", base_url="https://openrouter.ai/api/v1") // after cfg = TTSConfig(model="openai/gpt-4o-audio-preview", base_url="https://openrouter.ai/api/v1")
Defensive patterns
Strategy: try-catch
Try / catch
try:
audio, ct = await adapter.synthesize(text, config)
except VoiceProviderError as exc:
if "OpenRouter" in str(exc):
switch_to_native_tts_provider() # fallback path
raise Prevention
- Use audio-capable OpenRouter models for speech
- Test the model once after configuring it — a quick smoke synthesis catches unsupported-audio issues early
When it happens
Trigger: OpenRouter-style TTS config gets a 4xx/5xx from /audio/speech (e.g. model does not support audio output) and the OpenRouter hint applies, producing this combined message.
Common situations: Using an OpenRouter model that lacks native audio/speech support; the hint typically tells you to rely on the chat/completions audio fallback or pick an audio-capable model.
Related errors
- {exc}; original /audio/speech error: {original_error}
- No endpoint URL configured for this provider.
- TTS request error: {detail}
- OpenRouter chat audio returned no audio chunks; original /au
- OpenRouter chat audio returned invalid base64.
AI-assisted analysis of HKUDS/DeepTutor@3e82f13042 (2026-08-27).
Data as JSON: /api/errors/53be8210310519ce.
Report an issue: GitHub.