{"record":{"id":"01910f716a046b40","repo":"HKUDS/DeepTutor","slug":"stt-request-error-exc","errorCode":null,"errorMessage":"STT request error: {exc}","messagePattern":"STT request error: (.+?)","errorType":"exception","errorClass":"VoiceProviderError","httpStatus":null,"severity":"error","filePath":"deeptutor/services/voice/adapters/openai_compat.py","lineNumber":319,"sourceCode":"        content_type: str = \"application/octet-stream\",\n    ) -> str:\n        if not config.base_url:\n            raise VoiceProviderError(\"No endpoint URL configured for STT.\")\n        if not audio:\n            raise VoiceProviderError(\"No audio data to transcribe.\")\n        url = join_audio_path(config.base_url, \"audio/transcriptions\")\n        auth = build_auth_headers(config.auth_style, config.api_key)\n\n        try:\n            async with httpx.AsyncClient(timeout=config.request_timeout) as client:\n                if config.request_style == STT_BASE64_JSON:\n                    resp = await self._post_base64(client, url, auth, audio, filename, config)\n                else:\n                    resp = await self._post_multipart(\n                        client, url, auth, audio, filename, content_type, config\n                    )\n        except httpx.HTTPError as exc:\n            raise VoiceProviderError(f\"STT request error: {exc}\") from exc\n        _raise_for_provider(resp, \"Transcription\")\n        return self._parse_text(resp)\n\n    async def _post_multipart(\n        self,\n        client: httpx.AsyncClient,\n        url: str,\n        auth: dict[str, str],\n        audio: bytes,\n        filename: str,\n        content_type: str,\n        config: STTConfig,\n    ) -> httpx.Response:\n        files = {\n            \"file\": (filename, audio, normalize_stt_content_type(content_type)),\n        }\n        data: dict[str, str] = {\"model\": config.model, \"response_format\": \"json\"}\n        if config.language:","sourceCodeStart":301,"sourceCodeEnd":337,"githubUrl":"https://github.com/HKUDS/DeepTutor/blob/3e82f130422a813cdd73c10b21a44e9325f5821a/deeptutor/services/voice/adapters/openai_compat.py#L301-L337","documentation":"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.","triggerScenarios":"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.","commonSituations":"Long recordings exceeding request_timeout, wrong base_url host, proxy blocking multipart uploads, or upload-size limits resetting the connection.","solutions":["Increase STTConfig.request_timeout for long audio","Verify network egress and proxy handling of multipart uploads to base_url","Chunk or downsample long audio before transcription","Check the embedded httpx message to distinguish timeout vs connect errors"],"exampleFix":"// before\ncfg = STTConfig(base_url=url, api_key=key, request_timeout=10)\n// after\ncfg = STTConfig(base_url=url, api_key=key, request_timeout=120)","handlingStrategy":"retry","validationCode":"assert (stt_config.base_url or \"\").startswith((\"http://\", \"https://\"))\nassert len(audio) > 0","typeGuard":null,"tryCatchPattern":"for attempt in range(3):\n    try:\n        return await stt.transcribe(audio, stt_config)\n    except VoiceProviderError as exc:\n        if \"STT request error\" not in str(exc) or attempt == 2:\n            raise\n        await asyncio.sleep(2 ** attempt)","preventionTips":["Scale request_timeout with audio length","Compress/limit upload size for long recordings","Retry transport errors with backoff"],"tags":["voice","stt","network","timeout","httpx"],"backgroundTag":"http-request-failed","analyzedSha":"3e82f130422a813cdd73c10b21a44e9325f5821a","analyzedAt":"2026-08-27T06:57:25.364Z","schemaVersion":2},"datasetVersion":"2026-08-27T08:17:20.692Z"}