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

  1. Inspect e.status_code and the embedded Anthropic error type/message to identify the precise cause.
  2. 401/403 → fix the API key; 404/not_found_error → correct model or base_url path.
  3. 429 or 529 → retry with backoff, ideally through KeyPool rotation.
  4. 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

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


AI-assisted analysis of HKUDS/DeepTutor@3e82f13042 (2026-08-27). Data as JSON: /api/errors/cd15f4bca8c30e27. Report an issue: GitHub.