BerriAI/litellm · error · ValueError

Missing required fields in {content_type} block: {', '.join(

Error message

Missing required fields in {content_type} block: {', '.join(missing)}

What it means

The Anthropic content block's 'type' was recognized (tool_use or tool_result), but the block is missing one or more fields the TypedDict marks required (tool_use needs id/name/input; tool_result needs tool_use_id/content). The missing field names are listed in the message.

Source

Thrown at litellm/litellm_core_utils/token_counter.py:631

    Returns the corresponding TypedDict class if recognized, otherwise raises.
    """
    content_type: Final = content.get("type")
    if not content_type:
        raise ValueError("Anthropic content missing required field: 'type'")

    mapping: Final = {
        "tool_use": AnthropicMessagesToolUseParam,
        "tool_result": AnthropicMessagesToolResultParam,
    }

    expected_cls: Final = mapping.get(content_type)
    if expected_cls is None:
        raise ValueError(f"Unknown Anthropic content type: '{content_type}'")

    missing: Final = [k for k in getattr(expected_cls, "__required_keys__", set()) if k not in content]
    if missing:
        raise ValueError(f"Missing required fields in {content_type} block: {', '.join(missing)}")

    return expected_cls


def _count_anthropic_content(
    content: Mapping[str, Any],
    count_function: TokenCounterFunction,
    use_default_image_token_count: bool,
    default_token_count: int | None,
) -> int:
    """
    Count tokens in Anthropic-specific content blocks (tool_use, tool_result, etc.).

    Uses TypedDict definitions from litellm.types.llms.anthropic to determine
    what fields to count and how to handle nested structures.

    Dynamically infers which fields to count based on the TypedDict definition,
    avoiding hardcoded field names.

View on GitHub (pinned to 6c2dcb801b)

Solutions

  1. Add the listed missing fields - cross-check the block against Anthropic's docs for its type.
  2. When generating tool_result messages, always carry the id from the originating tool_use block.

Example fix

# before
result = {"type": "tool_result", "content": "22C"}

# after
result = {"type": "tool_result", "tool_use_id": tool_use_id, "content": "22C"}
Defensive patterns

Strategy: validation

Validate before calling

REQUIRED = {"tool_use": {"id", "name", "input"}, "tool_result": {"tool_use_id", "content"}}
missing = REQUIRED[block["type"]] - block.keys()
if missing:
    raise ValueError("missing " + str(missing))

Type guard

def is_complete_tool_block(block: dict) -> bool:
    req = {"tool_use": {"id", "name", "input"}, "tool_result": {"tool_use_id", "content"}}
    t = block.get("type")
    return t in req and req[t] <= block.keys()

Prevention

When it happens

Trigger: A tool_result block with content but no tool_use_id (common when echoing results); a tool_use block missing 'input'; blocks trimmed for storage and not restored before replay.

Common situations: Agent loops returning tool results and forgetting tool_use_id; persisting pared-down blocks then reusing them for token accounting; schema drift after Anthropic changed required fields.

Related errors


AI-assisted analysis of BerriAI/litellm@6c2dcb801b (2026-08-15). Data as JSON: /api/errors/1df4a5d8aacebe61. Report an issue: GitHub.