HKUDS/DeepTutor · error · VoiceProviderError

STT request error: {exc}

Error message

STT request error: {exc}

What it means

During transcription, the httpx POST to {base}/audio/transcriptions (multipart or base64-JSON style) raised httpx.HTTPError; the adapter wraps it as VoiceProviderError("STT request error: {exc}"). Transport-level failure of the STT call.

Source

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

        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,
        client: httpx.AsyncClient,
        url: str,
        auth: dict[str, str],
        audio: bytes,
        filename: str,
        content_type: str,
        config: STTConfig,
    ) -> httpx.Response:
        files = {
            "file": (filename, audio, normalize_stt_content_type(content_type)),
        }
        data: dict[str, str] = {"model": config.model, "response_format": "json"}
        if config.language:

View on GitHub (pinned to 3e82f13042)

Solutions

  1. Increase STTConfig.request_timeout for long audio
  2. Verify network egress and proxy handling of multipart uploads to base_url
  3. Chunk or downsample long audio before transcription
  4. Check the embedded httpx message to distinguish timeout vs connect errors

Example fix

// before
cfg = STTConfig(base_url=url, api_key=key, request_timeout=10)
// after
cfg = STTConfig(base_url=url, api_key=key, request_timeout=120)
Defensive patterns

Strategy: retry

Validate before calling

assert (stt_config.base_url or "").startswith(("http://", "https://"))
assert len(audio) > 0

Try / catch

for attempt in range(3):
    try:
        return await stt.transcribe(audio, stt_config)
    except VoiceProviderError as exc:
        if "STT request error" not in str(exc) or attempt == 2:
            raise
        await asyncio.sleep(2 ** attempt)

Prevention

When it happens

Trigger: DNS/connect/TLS failure or request_timeout exceeded while POSTing audio to the transcriptions endpoint. Large audio files with a short timeout are a classic trigger.

Common situations: Long recordings exceeding request_timeout, wrong base_url host, proxy blocking multipart uploads, or upload-size limits resetting the connection.

Understand the failure class

Background: 'Something went wrong' / 'Request failed (500)' / 'HTTP error! status: 404' — what failed HTTP requests actually mean and how to find the real cause — this error's family across 28 libraries.

Related errors


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