HKUDS/DeepTutor · error · VoiceProviderError
No audio data to transcribe.
Error message
No audio data to transcribe.
What it means
transcribe rejects empty audio input before making any request: if the bytes passed are empty (or a falsy value), VoiceProviderError("No audio data to transcribe.") is raised. This prevents pointless provider round-trips and confusing downstream errors.
Source
Thrown at deeptutor/services/voice/adapters/openai_compat.py:306
class OpenAICompatSTTAdapter(BaseSTTAdapter):
"""POST ``{base}/audio/transcriptions``.
Multipart ``file`` upload by default; OpenRouter uses a base64-JSON body
(``request_style == "base64_json"``) sharing the same path.
"""
async def transcribe(
self,
audio: bytes,
config: STTConfig,
*,
filename: str = "audio.webm",
content_type: str = "application/octet-stream",
) -> str:
if not config.base_url:
raise VoiceProviderError("No endpoint URL configured for STT.")
if not audio:
raise VoiceProviderError("No audio data to transcribe.")
url = join_audio_path(config.base_url, "audio/transcriptions")
auth = build_auth_headers(config.auth_style, config.api_key)
try:
async with httpx.AsyncClient(timeout=config.request_timeout) as client:
if config.request_style == STT_BASE64_JSON:
resp = await self._post_base64(client, url, auth, audio, filename, config)
else:
resp = await self._post_multipart(
client, url, auth, audio, filename, content_type, config
)
except httpx.HTTPError as exc:
raise VoiceProviderError(f"STT request error: {exc}") from exc
_raise_for_provider(resp, "Transcription")
return self._parse_text(resp)
async def _post_multipart(
self,View on GitHub (pinned to 3e82f13042)
Solutions
- Check audio length before calling transcribe; skip or prompt the user to re-record
- Fix the upstream capture path if recordings are systematically empty (permissions, codec, timing)
- In tests, use a real small audio fixture
Example fix
// before
if audio:
pass
text = await stt.transcribe(audio, cfg)
// after
if not audio:
return ""
text = await stt.transcribe(audio, cfg) Defensive patterns
Strategy: validation
Validate before calling
if not audio:
return "" # or prompt user to re-record
text = await stt.transcribe(audio, stt_config) Type guard
def has_audio_payload(audio: bytes | None) -> bool:
return bool(audio) Prevention
- Guard client-side: skip empty recordings before upload
- Enforce a minimum recording duration in the mic capture UI
When it happens
Trigger: Calling transcribe(b"", config) or transcribe with an empty buffer — e.g. a zero-length recording, a failed client-side capture, or an upload that produced no bytes.
Common situations: Browser mic permission granted but recording stopped instantly, WebSocket audio frame aggregation producing an empty blob, or a test passing an empty fixture.
Related errors
- Unsupported STT adapter: {name!r}
- {action} failed with HTTP {status_code}: {detail}
- No endpoint URL configured for STT.
- STT request error: {exc}
- Transcription response had no `text` field.
AI-assisted analysis of HKUDS/DeepTutor@3e82f13042 (2026-08-27).
Data as JSON: /api/errors/fa350d498f58d8bc.
Report an issue: GitHub.