HKUDS/DeepTutor · error · LLMAPIError
OpenAI API error: {error_text}
Error message
OpenAI API error: {error_text} What it means
Raised inside _openai_complete when the OpenAI-compatible endpoint returns a non-2xx status after the retry/retry-after handling branch did not apply. The raw response body (error_text) is embedded in the LLMAPIError along with status_code and provider, so the message mirrors whatever the server returned (e.g. 401 invalid key, 400 bad request, 429 exhausted).
Source
Thrown at deeptutor/services/llm/cloud_provider.py:426
if isinstance(first_choice, Mapping):
message = cast(Mapping[str, object], first_choice).get(
"message"
)
else:
message = None
if isinstance(message, Mapping):
content = extract_response_content(
cast(dict[str, object], message)
)
else:
retry_text = await retry_resp.text()
raise LLMAPIError(
f"OpenAI API error: {retry_text}",
status_code=retry_resp.status,
provider=binding or "openai",
)
else:
raise LLMAPIError(
f"OpenAI API error: {error_text}",
status_code=resp.status,
provider=binding or "openai",
)
except aiohttp.ClientError as e:
# Handle connection errors with more specific messages
if "forcibly closed" in str(e).lower() or "10054" in str(e):
raise LLMAPIError(
f"Connection to {binding} API was forcibly closed. "
"This may indicate network issues or server-side problems. "
"Please check your internet connection and try again.",
status_code=0,
provider=binding or "openai",
) from e
else:
raise LLMAPIError(
f"Network error connecting to {binding} API: {e}",
status_code=0,View on GitHub (pinned to 3e82f13042)
Solutions
- Read status_code and error_text from the LLMAPIError to see the server's own message.
- Fix the underlying cause: correct base_url, valid model name for that endpoint, valid API key.
- If the error mentions response_format, remove it or rely on the runtime disable_response_format_at_runtime retry.
- For 429/5xx, add backoff retries at the caller or use KeyPool rotation.
Example fix
// before
resp = await complete(prompt=p, model=m, base_url="http://localhost:8000")
# after
try:
resp = await complete(prompt=p, model=m, base_url="http://localhost:8000/v1")
except LLMAPIError as e:
if e.status_code == 404:
raise RuntimeError(f"Bad base_url or model: {e}") from e
raise Defensive patterns
Strategy: try-catch
Validate before calling
# Not fully avoidable: server-side decision. Pre-check what you control:
assert (model or "").strip(), "model required"
assert base_url is None or base_url.startswith("http"), "base_url malformed" Try / catch
try:
out = await complete(prompt=p, model=m, api_key=k, base_url=u)
except LLMAPIError as e:
if e.status_code == 401:
refresh_key()
elif e.status_code == 429:
await asyncio.sleep(30)
else:
log.error("provider %s status %s: %s", e.provider, e.status_code, e)
raise Prevention
- Always inspect status_code on LLMAPIError before deciding to retry.
- Validate model names against the endpoint's model list at startup.
- Keep base_url pointing at the documented API path.
When it happens
Trigger: POSTing to an OpenAI-compatible chat completions endpoint that replies 400 (malformed payload/unsupported param), 401/403 (bad key), 404 (wrong base_url path), or 500; using a proxy or local server (vLLM, LM Studio, Ollama's OpenAI shim) that returns an error body.
Common situations: Misconfigured base_url pointing at the wrong path; provider rejects response_format or a tool param; model name not available on the endpoint; expired or revoked API key; reverse proxy returning HTML error pages.
Related errors
- OpenAI stream error: {error_text}
- Cloud completion failed: no valid configuration
- Anthropic API error: {error_text}
- Anthropic stream error: {error_text}
- Cohere API error: {error_text}
AI-assisted analysis of HKUDS/DeepTutor@3e82f13042 (2026-08-27).
Data as JSON: /api/errors/1c002dda5513092d.
Report an issue: GitHub.