{"record":{"id":"fb39f08f339a0cce","repo":"BerriAI/litellm","slug":"unknown-anthropic-content-type-content-type","errorCode":null,"errorMessage":"Unknown Anthropic content type: '{content_type}'","messagePattern":"Unknown Anthropic content type: '(.+?)'","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"litellm/litellm_core_utils/token_counter.py","lineNumber":627,"sourceCode":"\ndef _validate_anthropic_content(content: Mapping[str, Any]) -> type:\n    \"\"\"\n    Validate and determine which Anthropic TypedDict applies.\n\n    Returns the corresponding TypedDict class if recognized, otherwise raises.\n    \"\"\"\n    content_type: Final = content.get(\"type\")\n    if not content_type:\n        raise ValueError(\"Anthropic content missing required field: 'type'\")\n\n    mapping: Final = {\n        \"tool_use\": AnthropicMessagesToolUseParam,\n        \"tool_result\": AnthropicMessagesToolResultParam,\n    }\n\n    expected_cls: Final = mapping.get(content_type)\n    if expected_cls is None:\n        raise ValueError(f\"Unknown Anthropic content type: '{content_type}'\")\n\n    missing: Final = [k for k in getattr(expected_cls, \"__required_keys__\", set()) if k not in content]\n    if missing:\n        raise ValueError(f\"Missing required fields in {content_type} block: {', '.join(missing)}\")\n\n    return expected_cls\n\n\ndef _count_anthropic_content(\n    content: Mapping[str, Any],\n    count_function: TokenCounterFunction,\n    use_default_image_token_count: bool,\n    default_token_count: int | None,\n) -> int:\n    \"\"\"\n    Count tokens in Anthropic-specific content blocks (tool_use, tool_result, etc.).\n\n    Uses TypedDict definitions from litellm.types.llms.anthropic to determine","sourceCodeStart":609,"sourceCodeEnd":645,"githubUrl":"https://github.com/BerriAI/litellm/blob/6c2dcb801bf2b75c18f1bb24140e7cf57465cc4d/litellm/litellm_core_utils/token_counter.py#L609-L645","documentation":"An Anthropic content block's 'type' is not one of the two tool-related types this validator recognizes ('tool_use' or 'tool_result'). Since the helper only runs for tool-shaped blocks, an unknown type means malformed or misplaced content - e.g. text/image blocks misrouted, or typos like 'tool-use'.","triggerScenarios":"A block with type='tool-use' (hyphen instead of underscore), type='toolcall', or a text/image block incorrectly dispatched into the tool-block validator on the token-counting path.","commonSituations":"Hand-written Anthropic message builders guessing at type names; converting from other vendor schemas with different discriminators; case errors like 'ToolUse'.","solutions":["Use the exact Anthropic snake_case types: 'tool_use' and 'tool_result' for tool blocks; 'text' and 'image' for others.","Validate your builder against the official Anthropic messages schema."],"exampleFix":"# before\nblock = {\"type\": \"tool-use\", \"id\": \"t1\", \"name\": \"get_weather\", \"input\": {}}\n\n# after\nblock = {\"type\": \"tool_use\", \"id\": \"t1\", \"name\": \"get_weather\", \"input\": {}}","handlingStrategy":"validation","validationCode":"KNOWN = {\"tool_use\", \"tool_result\", \"text\", \"image\", \"thinking\"}\nif block.get(\"type\") not in KNOWN:\n    raise ValueError(\"bad content type \" + repr(block.get(\"type\")))","typeGuard":"def is_known_anthropic_tool_type(block: dict) -> bool:\n    return block.get(\"type\") in (\"tool_use\", \"tool_result\")","tryCatchPattern":null,"preventionTips":["Use exact snake_case Anthropic type strings; add a unit test asserting the vocabulary.","Prefer litellm's conversion utilities over hand-rolled OpenAI-to-Anthropic mappers."],"tags":["token-counter","anthropic","validation","schema"],"backgroundTag":null,"analyzedSha":"6c2dcb801bf2b75c18f1bb24140e7cf57465cc4d","analyzedAt":"2026-08-15T07:12:03.035Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}