{"record":{"id":"cd15f4bca8c30e27","repo":"HKUDS/DeepTutor","slug":"anthropic-api-error-error-text","errorCode":null,"errorMessage":"Anthropic API error: {error_text}","messagePattern":"Anthropic API error: (.+?)","errorType":"http","errorClass":"LLMAPIError","httpStatus":null,"severity":"error","filePath":"deeptutor/services/llm/cloud_provider.py","lineNumber":706,"sourceCode":"    max_tokens_value = max_tokens if max_tokens is not None else 4096\n    temperature_value = temperature if temperature is not None else 0.7\n    data: dict[str, object] = {\n        \"model\": model,\n        \"system\": system_content,\n        \"messages\": msg_list,\n        \"max_tokens\": max_tokens_value,\n        \"temperature\": temperature_value,\n    }\n\n    timeout = aiohttp.ClientTimeout(total=120)\n    connector = _get_aiohttp_connector()\n    async with aiohttp.ClientSession(\n        timeout=timeout, connector=connector, trust_env=True\n    ) as session:\n        async with session.post(url, headers=headers, json=data) as response:\n            if response.status != 200:\n                error_text = await response.text()\n                raise LLMAPIError(\n                    f\"Anthropic API error: {error_text}\",\n                    status_code=response.status,\n                    provider=\"anthropic\",\n                )\n\n            result = cast(dict[str, object], await response.json())\n            content_items = result.get(\"content\")\n            if isinstance(content_items, list) and content_items:\n                content_list = cast(list[object], content_items)\n                first_item = content_list[0]\n                if isinstance(first_item, Mapping):\n                    text = cast(Mapping[str, object], first_item).get(\"text\")\n                    if isinstance(text, str):\n                        return text\n            raise LLMAPIError(\n                \"Anthropic API error: unexpected response payload\",\n                status_code=response.status,\n                provider=\"anthropic\",","sourceCodeStart":688,"sourceCodeEnd":724,"githubUrl":"https://github.com/HKUDS/DeepTutor/blob/3e82f130422a813cdd73c10b21a44e9325f5821a/deeptutor/services/llm/cloud_provider.py#L688-L724","documentation":"_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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before\nout = await complete(prompt=p, binding=\"anthropic\", model=\"claude-sonnet-4\", api_key=k)\n\n# after\ntry:\n    out = await complete(prompt=p, binding=\"anthropic\", model=\"claude-sonnet-4\", api_key=k)\nexcept LLMAPIError as e:\n    if e.status_code in (429, 529):\n        await asyncio.sleep(20)\n    raise","handlingStrategy":"try-catch","validationCode":"# Partial: verify the model is offered before a long prompt\n# GET {base}/v1/models with the same key; skip if unsupported","typeGuard":null,"tryCatchPattern":"try:\n    out = await complete(prompt=p, binding=\"anthropic\", model=m, api_key=k)\nexcept LLMAPIError as e:\n    if e.status_code in (429, 529):\n        await asyncio.sleep(20); retry()\n    elif e.status_code == 401:\n        rotate_key()\n    else:\n        raise","preventionTips":["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."],"tags":["llm","anthropic","http-error","rate-limit"],"backgroundTag":"llm-api-http-error","analyzedSha":"3e82f130422a813cdd73c10b21a44e9325f5821a","analyzedAt":"2026-08-27T06:57:25.364Z","schemaVersion":2},"datasetVersion":"2026-08-27T08:17:20.692Z"}