{"record":{"id":"8f3577659803b9bf","repo":"BerriAI/litellm","slug":"anthropic-content-missing-required-field-type","errorCode":null,"errorMessage":"Anthropic content missing required field: 'type'","messagePattern":"Anthropic content missing required field: 'type'","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"litellm/litellm_core_utils/token_counter.py","lineNumber":618,"sourceCode":"            raise ValueError(\"Empty image_url string is not valid.\")\n        return calculate_img_tokens(\n            data=image_url,\n            mode=\"auto\",\n            use_default_image_token_count=use_default_image_token_count,\n        )\n    else:\n        raise ValueError(f\"Invalid image_url type: {type(image_url).__name__}. Expected str or dict with 'url' field.\")\n\n\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(","sourceCodeStart":600,"sourceCodeEnd":636,"githubUrl":"https://github.com/BerriAI/litellm/blob/6c2dcb801bf2b75c18f1bb24140e7cf57465cc4d/litellm/litellm_core_utils/token_counter.py#L600-L636","documentation":"While counting Anthropic-format messages, a content block dict lacks the required 'type' key. Anthropic content blocks are discriminated solely by 'type' (tool_use, tool_result, text, ...); without it litellm cannot select a TypedDict to validate against, so it fails fast.","triggerScenarios":"Content blocks like {\"text\": \"hi\"} (type omitted), a block with type=None, or blocks assembled from dict merges that dropped the key, passed to token_counter on the Anthropic path.","commonSituations":"Hand-converting OpenAI-style content to Anthropic format; storing blocks without the discriminator; None 'type' from optional-access patterns.","solutions":["Ensure every content block dict has an explicit 'type' (\"text\", \"image\", \"tool_use\", \"tool_result\", \"thinking\").","For plain text prefer a plain string instead of a dict block."],"exampleFix":"# before\ncontent = [{\"text\": \"What's the weather?\"}]\n\n# after\ncontent = [{\"type\": \"text\", \"text\": \"What's the weather?\"}]","handlingStrategy":"validation","validationCode":"for block in content:\n    if isinstance(block, dict) and not block.get(\"type\"):\n        block[\"type\"] = \"text\"  # or raise, depending on your policy","typeGuard":"def has_type_key(block: dict) -> bool:\n    return bool(block.get(\"type\"))","tryCatchPattern":null,"preventionTips":["Always emit 'type' when constructing Anthropic content blocks.","For plain text, use a bare string content value instead of a dict."],"tags":["token-counter","anthropic","validation","missing-field"],"backgroundTag":null,"analyzedSha":"6c2dcb801bf2b75c18f1bb24140e7cf57465cc4d","analyzedAt":"2026-08-15T07:12:03.035Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}