BerriAI/litellm · error · ValueError

tool call not supported: {tool_call}

Error message

tool call not supported: {tool_call}

What it means

Raised while transforming assistant tool_calls into Responses API input items: a tool call whose 'function' field is neither the standard OpenAI shape (with name/arguments) nor a dict-based custom tool call. The bridge only knows how to convert function tool calls and custom tool calls; anything else (e.g. provider-specific tool call formats) is rejected.

Source

Thrown at litellm/completion_extras/litellm_responses_transformation/transformation.py:346

                            "type": "function_call",
                            "call_id": tool_call["id"],
                        }
                        if "name" in function:
                            input_tool_call["name"] = function["name"]
                        if "arguments" in function:
                            input_tool_call["arguments"] = function["arguments"]
                        input_items.append(input_tool_call)
                    elif isinstance(custom, dict):
                        input_items.append(
                            ResponseCustomToolCallParam(
                                type="custom_tool_call",
                                call_id=tool_call["id"],
                                name=custom.get("name", ""),
                                input=custom.get("input", ""),
                            )
                        )
                    else:
                        raise ValueError(f"tool call not supported: {tool_call}")
            elif content is not None:
                if role == "assistant":
                    for r_item in _get_reasoning_items(msg):
                        input_items.append(_reasoning_item_to_response_input(r_item))
                input_items.append(
                    {
                        "type": "message",
                        "role": role,
                        "content": self._convert_content_to_responses_format(content, cast(str, role)),
                    }
                )

        return input_items, instructions

    def _map_optional_params_to_responses_api_request(
        self,
        optional_params: dict,
        responses_api_request: "ResponsesAPIOptionalRequestParams",

View on GitHub (pinned to 6c2dcb801b)

Solutions

  1. Normalize prior assistant tool_calls to the OpenAI shape before replaying: each entry needs id, type='function', function={'name': str, 'arguments': str}
  2. If the tool call was a custom/freeform tool, ensure the 'function' field is a dict with 'name' and 'input'
  3. Re-run the original tool-calling turn through the same provider so the replayed format matches
  4. Bypass the responses bridge for that call if you must preserve a foreign tool call format

Example fix

# before
messages = [
  {"role": "assistant", "tool_calls": [
      {"id": "t1", "type": "tool_use", "input": {"city": "SF"}}  # non-OpenAI shape
  ]},
]

# after
import json
messages = [
  {"role": "assistant", "tool_calls": [
      {"id": "t1", "type": "function",
       "function": {"name": "get_weather", "arguments": json.dumps({"city": "SF"})}}
  ]},
]
Defensive patterns

Strategy: validation

Validate before calling

def tool_calls_bridge_safe(tool_calls: list) -> bool:
    for tc in tool_calls:
        fn = tc.get("function") if isinstance(tc, dict) else None
        if not (isinstance(fn, dict) and "arguments" in fn):
            return False
    return True

Type guard

def is_openai_tool_call(tc) -> bool:
    return (
        isinstance(tc, dict)
        and isinstance(tc.get("function"), dict)
        and isinstance(tc["function"].get("arguments"), str)
    )

Try / catch

try:
    resp = litellm.completion(**bridge_kwargs)
except ValueError as e:
    if "tool call not supported" in str(e):
        # drop history tool_calls and retry with a text summary of the tool result
        bridge_kwargs["messages"] = sanitize_tool_calls(bridge_kwargs["messages"])
        resp = litellm.completion(**bridge_kwargs)
    else:
        raise

Prevention

When it happens

Trigger: Sending back an assistant message whose tool_calls entries come from a non-OpenAI provider (e.g. Anthropic-style tool_use blocks put directly into tool_calls), or a tool_call dict missing/typing 'function' as a non-dict, while the request is routed through the chat→responses bridge.

Common situations: Multi-turn agent loops that replay tool calls captured from a different provider; hand-crafted assistant tool_call dicts; converting between provider SDK formats without normalization.

Related errors


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