HKUDS/DeepTutor · error · LLMAPIError
Anthropic API error: {error_text}
Error message
Anthropic API error: {error_text} What it means
_anthropic_complete POSTs to {base_url}/v1/messages and, on any non-200 status, reads the body and raises LLMAPIError carrying the raw Anthropic error JSON (type/message), the status code, and provider='anthropic'. Unlike the OpenAI path there is no retry ladder — the first non-200 is fatal.
Source
Thrown at deeptutor/services/llm/cloud_provider.py:706
max_tokens_value = max_tokens if max_tokens is not None else 4096
temperature_value = temperature if temperature is not None else 0.7
data: dict[str, object] = {
"model": model,
"system": system_content,
"messages": msg_list,
"max_tokens": max_tokens_value,
"temperature": temperature_value,
}
timeout = aiohttp.ClientTimeout(total=120)
connector = _get_aiohttp_connector()
async with aiohttp.ClientSession(
timeout=timeout, connector=connector, trust_env=True
) as session:
async with session.post(url, headers=headers, json=data) as response:
if response.status != 200:
error_text = await response.text()
raise LLMAPIError(
f"Anthropic API error: {error_text}",
status_code=response.status,
provider="anthropic",
)
result = cast(dict[str, object], await response.json())
content_items = result.get("content")
if isinstance(content_items, list) and content_items:
content_list = cast(list[object], content_items)
first_item = content_list[0]
if isinstance(first_item, Mapping):
text = cast(Mapping[str, object], first_item).get("text")
if isinstance(text, str):
return text
raise LLMAPIError(
"Anthropic API error: unexpected response payload",
status_code=response.status,
provider="anthropic",View on GitHub (pinned to 3e82f13042)
Solutions
- Inspect e.status_code and the embedded Anthropic error type/message to identify the precise cause.
- 401/403 → fix the API key; 404/not_found_error → correct model or base_url path.
- 429 or 529 → retry with backoff, ideally through KeyPool rotation.
- 400 → check max_tokens is within the model's limit and payload schema is valid.
Example fix
// before
out = await complete(prompt=p, binding="anthropic", model="claude-sonnet-4", api_key=k)
# after
try:
out = await complete(prompt=p, binding="anthropic", model="claude-sonnet-4", api_key=k)
except LLMAPIError as e:
if e.status_code in (429, 529):
await asyncio.sleep(20)
raise Defensive patterns
Strategy: try-catch
Validate before calling
# Partial: verify the model is offered before a long prompt
# GET {base}/v1/models with the same key; skip if unsupported Try / catch
try:
out = await complete(prompt=p, binding="anthropic", model=m, api_key=k)
except LLMAPIError as e:
if e.status_code in (429, 529):
await asyncio.sleep(20); retry()
elif e.status_code == 401:
rotate_key()
else:
raise Prevention
- Back off on 429/529 — Anthropic overload is common at peak times.
- Keep max_tokens within model limits to avoid 400s.
- Wrap keys in KeyPool so strikes trigger rotation automatically.
When it happens
Trigger: 401 invalid x-api-key; 400 from a malformed model name or too-large max_tokens; 429 rate-limited by Anthropic; 529/503 overloaded; wrong base_url when proxying Anthropic.
Common situations: Free-tier rate limits on Claude; using an Anthropic-compatible proxy with a different path prefix; model string not available to the account; anthropic-version header mismatch on custom gateways.
Related errors
- Anthropic stream error: {error_text}
- Cohere API error: {error_text}
- OpenAI API error: {error_text}
- OpenAI stream error: {error_text}
- Anthropic API key is missing from the active LLM profile.
AI-assisted analysis of HKUDS/DeepTutor@3e82f13042 (2026-08-27).
Data as JSON: /api/errors/cd15f4bca8c30e27.
Report an issue: GitHub.