{"record":{"id":"941b6912440e5614","repo":"HKUDS/DeepTutor","slug":"anthropic-api-error-unexpected-response-payload","errorCode":null,"errorMessage":"Anthropic API error: unexpected response payload","messagePattern":"Anthropic API error: unexpected response payload","errorType":"http","errorClass":"LLMAPIError","httpStatus":null,"severity":"error","filePath":"deeptutor/services/llm/cloud_provider.py","lineNumber":721,"sourceCode":"        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\",\n            )\n\n\nasync def _anthropic_stream(\n    model: str,\n    prompt: str,\n    system_prompt: str,\n    api_key: str | None,\n    base_url: str | None,\n    messages: list[dict[str, object]] | None = None,\n    max_tokens: int | None = None,\n    temperature: float | None = None,\n) -> AsyncGenerator[str, None]:\n    \"\"\"Anthropic (Claude) API streaming.\"\"\"\n    import json","sourceCodeStart":703,"sourceCodeEnd":739,"githubUrl":"https://github.com/HKUDS/DeepTutor/blob/3e82f130422a813cdd73c10b21a44e9325f5821a/deeptutor/services/llm/cloud_provider.py#L703-L739","documentation":"After a 200 response, _anthropic_complete walks result['content'][0]['text'] through a chain of isinstance/Mapping casts; if any level is missing or not a string, LLMAPIError 'unexpected response payload' is raised with the (successful) status code. It means the endpoint returned 200 JSON that does not match Anthropic's Messages schema.","triggerScenarios":"A mock, proxy, or Anthropic-compatible gateway returning {\"content\": []} or content items without a text field; empty completion where Anthropic returns an empty content array (possible with certain stop/tool configurations); schema drift after an API revision.","commonSituations":"Testing against stub servers with hand-rolled response fixtures; middleboxes rewriting the body; very rare real-API schema changes or empty model outputs.","solutions":["Log the full response JSON once to compare against the documented Messages schema.","Fix mock/proxy fixtures to include content: [{type: 'text', text: '...'}].","If hitting the real API, confirm base_url is not pointed at a non-Anthropic endpoint.","Report/patch if a provider revision changed the payload shape."],"exampleFix":"// before\n# mock server\n{\"content\": [{\"type\": \"text\", \"body\": \"hi\"}]}\n\n# after\n{\"content\": [{\"type\": \"text\", \"text\": \"hi\"}]}","handlingStrategy":"type-guard","validationCode":"# Not applicable (server-side payload); pin conforming endpoints only","typeGuard":"def is_anthropic_messages_payload(result: dict) -> bool:\n    content = result.get(\"content\")\n    return (\n        isinstance(content, list)\n        and bool(content)\n        and isinstance(content[0], dict)\n        and isinstance(content[0].get(\"text\"), str)\n    )","tryCatchPattern":"try:\n    out = await complete(prompt=p, binding=\"anthropic\", model=m, api_key=k)\nexcept LLMAPIError as e:\n    if \"unexpected response payload\" in str(e):\n        log.error(\"nonstandard Anthropic endpoint; raw body needed\")\n    raise","preventionTips":["Validate mock/proxy fixtures against the documented Messages schema.","Log raw bodies when integrating Anthropic-compatible gateways.","Avoid middleboxes that rewrite response JSON."],"tags":["llm","anthropic","unexpected-payload","schema"],"backgroundTag":"unexpected-response-schema","analyzedSha":"3e82f130422a813cdd73c10b21a44e9325f5821a","analyzedAt":"2026-08-27T06:57:25.364Z","schemaVersion":2},"datasetVersion":"2026-08-27T08:17:20.692Z"}