BerriAI/litellm · error · ValueError

Unexpected key {key!r}; expected 'tool_calls' or 'function_c

Error message

Unexpected key {key!r}; expected 'tool_calls' or 'function_call'

What it means

Internal invariant violation: _count_function_call_tokens only handles the keys 'tool_calls' and 'function_call', and it was invoked with a different key. User code cannot normally reach this from public APIs - it indicates a LiteLLM internal dispatch bug or a monkey-patched/vendored copy of the helper.

Source

Thrown at litellm/litellm_core_utils/token_counter.py:431

    `function_call` dict. Only the `arguments` string is counted (matching the
    existing tool_calls behavior); names are accounted for elsewhere via the
    tool/function definitions and `tool_choice`.
    """
    if key == "tool_calls":
        if not isinstance(value, list):
            raise ValueError(f"Unsupported type {type(value)} for key tool_calls in message {message}")
        total = 0
        for tool_call in value:
            if "function" not in tool_call:
                raise ValueError(f"Unsupported tool call {tool_call} must contain a function key")
            function_arguments = tool_call["function"].get("arguments", "")
            total += count_function(str(function_arguments))
        return total
    if key == "function_call":
        if not isinstance(value, Mapping):
            raise ValueError(f"Unsupported type {type(value)} for key function_call in message {message}")
        return count_function(str(value.get("arguments", "")))
    raise ValueError(f"Unexpected key {key!r}; expected 'tool_calls' or 'function_call'")


def _count_messages(
    params: _MessageCountParams,
    messages: list[AllMessageValues],
    use_default_image_token_count: bool,
    default_token_count: int | None,
) -> int:
    """
    Count the number of tokens in a list of messages.

    Args:
        params (_MessageCountParams): The parameters for counting tokens.
        messages (List[AllMessageValues]): The list of messages to count tokens in.
        use_default_image_token_count (bool): When True, will NOT make a GET request to the image URL and instead return the default image dimensions.
        default_token_count (Optional[int]): The default number of tokens to return for a message block, if an error occurs.
    """
    num_tokens = 0

View on GitHub (pinned to 6c2dcb801b)

Solutions

  1. If calling the private helper directly, pass only 'tool_calls' or 'function_call'.
  2. Reinstall litellm cleanly (pip install --force-reinstall litellm) to remove mixed/stale copies.
  3. If it fires from an unmodified install, report upstream with the full traceback.
Defensive patterns

Strategy: try-catch

Try / catch

try:
    n = litellm.token_counter(model=m, messages=msgs)
except ValueError as e:
    if "Unexpected key" in str(e):
        report_bug_with_traceback(e)  # internal invariant - not caller-fixable
    raise

Prevention

When it happens

Trigger: A modified or partially upgraded litellm install where the dispatch passes a different key; calling the private helper directly with e.g. key='tools'.

Common situations: Editing litellm internals or vendoring parts of token_counter.py; mixed/stale installations after a partial upgrade (stale .pyc, multiple site-packages copies).

Related errors


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