HKUDS/DeepTutor · error · LLMAPIError
OpenAI stream error: {error_text}
Error message
OpenAI stream error: {error_text} What it means
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.
Source
Thrown at deeptutor/services/llm/cloud_provider.py:568
retry_attempt == 0
and resp.status == 400
and "response_format" in attempt_data
and _looks_like_unsupported_response_format(error_text)
):
logger.warning(
"Provider %s rejected response_format for model %s "
"(HTTP 400); retrying stream without it. Body: %s",
binding,
model,
error_text[:200],
)
disable_response_format_at_runtime(binding, model)
attempt_data = dict(attempt_data)
attempt_data.pop("response_format", None)
await resp_cm.__aexit__(None, None, None)
continue
await resp_cm.__aexit__(None, None, None)
raise LLMAPIError(
f"OpenAI stream error: {error_text}",
status_code=resp.status,
provider=binding or "openai",
)
except BaseException:
await resp_cm.__aexit__(None, None, None)
raise
try:
# Track thinking block state for streaming
in_thinking_block = False
thinking_buffer = ""
async for line in resp.content:
line_str = line.decode("utf-8").strip()
if not line_str or not line_str.startswith("data:"):
continue
View on GitHub (pinned to 3e82f13042)
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.
Example fix
// before
async for chunk in stream(prompt=p, model=m):
...
# after
try:
async for chunk in stream(prompt=p, model=m):
...
except LLMAPIError as e:
if e.status_code == 429:
await asyncio.sleep(30)
raise Defensive patterns
Strategy: retry
Validate before calling
# Nothing to validate client-side beyond auth/model; do a cheap reachability check:
async with aiohttp.ClientSession() as s:
async with s.get(base_url or "https://api.openai.com/v1/models") as r:
if r.status in (401, 404):
raise RuntimeError("stream pre-check failed") Try / catch
try:
async for chunk in stream(prompt=p, model=m):
buf.append(chunk)
except LLMAPIError as e:
if e.status_code in (429, 500, 503):
await asyncio.sleep(2 ** attempt)
# retry loop
else:
raise Prevention
- 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.
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- OpenAI API error: {error_text}
- Anthropic stream error: {error_text}
- Cloud completion failed: no valid configuration
- Anthropic API error: {error_text}
- Cohere API error: {error_text}
AI-assisted analysis of HKUDS/DeepTutor@3e82f13042 (2026-08-27).
Data as JSON: /api/errors/0d267e04a2266a66.
Report an issue: GitHub.