{"record":{"id":"0d267e04a2266a66","repo":"HKUDS/DeepTutor","slug":"openai-stream-error-error-text","errorCode":null,"errorMessage":"OpenAI stream error: {error_text}","messagePattern":"OpenAI stream error: (.+?)","errorType":"http","errorClass":"LLMAPIError","httpStatus":null,"severity":"error","filePath":"deeptutor/services/llm/cloud_provider.py","lineNumber":568,"sourceCode":"                    retry_attempt == 0\n                    and resp.status == 400\n                    and \"response_format\" in attempt_data\n                    and _looks_like_unsupported_response_format(error_text)\n                ):\n                    logger.warning(\n                        \"Provider %s rejected response_format for model %s \"\n                        \"(HTTP 400); retrying stream without it. Body: %s\",\n                        binding,\n                        model,\n                        error_text[:200],\n                    )\n                    disable_response_format_at_runtime(binding, model)\n                    attempt_data = dict(attempt_data)\n                    attempt_data.pop(\"response_format\", None)\n                    await resp_cm.__aexit__(None, None, None)\n                    continue\n                await resp_cm.__aexit__(None, None, None)\n                raise LLMAPIError(\n                    f\"OpenAI stream error: {error_text}\",\n                    status_code=resp.status,\n                    provider=binding or \"openai\",\n                )\n            except BaseException:\n                await resp_cm.__aexit__(None, None, None)\n                raise\n\n        try:\n            # Track thinking block state for streaming\n            in_thinking_block = False\n            thinking_buffer = \"\"\n\n            async for line in resp.content:\n                line_str = line.decode(\"utf-8\").strip()\n                if not line_str or not line_str.startswith(\"data:\"):\n                    continue\n","sourceCodeStart":550,"sourceCodeEnd":586,"githubUrl":"https://github.com/HKUDS/DeepTutor/blob/3e82f130422a813cdd73c10b21a44e9325f5821a/deeptutor/services/llm/cloud_provider.py#L550-L586","documentation":"Raised in _openai_stream when the SSE POST returns a non-2xx status before any chunks are yielded (the response_format retry branch has already been exhausted or did not apply). The response body text is embedded in LLMAPIError along with status_code and provider, mirroring the server's error message.","triggerScenarios":"Starting a stream against an endpoint that immediately replies 401 (bad key), 400 (invalid model/param), or 429; mid-stream failures typically surface differently — this fires on the initial status check.","commonSituations":"Expired API key discovered only when streaming; model name typo'd for the endpoint; strict gateways rejecting stream:true; rate limits hit before stream start.","solutions":["Read e.status_code and the embedded error_text to identify the server-side reason.","Correct auth/model/base_url per the status (401 → key, 404 → url/model, 429 → backoff).","For 429, retry with backoff or enable KeyPool rotation before re-streaming.","If a gateway rejects streaming, call non-streaming complete() as a fallback path."],"exampleFix":"// before\nasync for chunk in stream(prompt=p, model=m):\n    ...\n\n# after\ntry:\n    async for chunk in stream(prompt=p, model=m):\n        ...\nexcept LLMAPIError as e:\n    if e.status_code == 429:\n        await asyncio.sleep(30)\n    raise","handlingStrategy":"retry","validationCode":"# Nothing to validate client-side beyond auth/model; do a cheap reachability check:\nasync with aiohttp.ClientSession() as s:\n    async with s.get(base_url or \"https://api.openai.com/v1/models\") as r:\n        if r.status in (401, 404):\n            raise RuntimeError(\"stream pre-check failed\")","typeGuard":null,"tryCatchPattern":"try:\n    async for chunk in stream(prompt=p, model=m):\n        buf.append(chunk)\nexcept LLMAPIError as e:\n    if e.status_code in (429, 500, 503):\n        await asyncio.sleep(2 ** attempt)\n        # retry loop\n    else:\n        raise","preventionTips":["Pre-check credentials/model with a cheap non-streaming call when sanity matters.","Degrade to complete() when the gateway rejects streaming.","Centralize status-code-based retry policy instead of scattering it."],"tags":["llm","streaming","openai","http-error"],"backgroundTag":"llm-api-http-error","analyzedSha":"3e82f130422a813cdd73c10b21a44e9325f5821a","analyzedAt":"2026-08-27T06:57:25.364Z","schemaVersion":2},"datasetVersion":"2026-08-27T08:17:20.692Z"}