sgl-project/sglang · error · ValueError
tool_choice references tool {tool_name!r} but it is not in t
Error message
tool_choice references tool {tool_name!r} but it is not in the forwarded tools list (server-side Anthropic tools cannot be selected) What it means
Raised during Anthropic-to-OpenAI-compatible request conversion when tool_choice names a specific tool (type='tool' with a name, or the legacy 'function' form) that is not present in the request's tools list. SGLang only forwards client-supplied custom tools to the backend; server-side Anthropic built-in tools (web_search, code_execution, etc.) cannot be selected, so an unmatched name is a 400.
Source
Thrown at python/sglang/srt/entrypoints/anthropic/serving.py:714
if anthropic_request.tool_choice is not None:
tc_type = anthropic_request.tool_choice.type
if tc_type == "none":
chat_request.tool_choice = "none"
elif chat_request.tools:
if tc_type == "auto":
chat_request.tool_choice = "auto"
elif tc_type == "any":
chat_request.tool_choice = "required"
elif tc_type == "tool":
tool_name = anthropic_request.tool_choice.name
# ``Tool.function`` is a ``Function`` Pydantic model, not
# a dict — access by attribute. A dict ``.get`` would
# AttributeError and surface as a 500 instead of the
# intended 400 / happy path.
if not any(
t.function.name == tool_name for t in chat_request.tools
):
raise ValueError(
f"tool_choice references tool {tool_name!r} but it "
f"is not in the forwarded tools list "
f"(server-side Anthropic tools cannot be selected)"
)
chat_request.tool_choice = ToolChoice(
type="function",
function=ToolChoiceFuncName(name=tool_name),
)
elif tc_type in ("any", "tool"):
raise ValueError(
f"tool_choice={tc_type!r} requires at least one custom "
f"tool; all supplied tools were server-side Anthropic "
f"built-ins which the OpenAI-compatible backend cannot "
f"invoke"
)
elif chat_request.tools:
chat_request.tool_choice = "auto"
View on GitHub (pinned to 0132848349)
Solutions
- Make tool_choice.name exactly match a tool's name field in the same request's tools array
- Do not reference server-side Anthropic built-in tools in tool_choice — define a custom tool instead
- Use tool_choice type 'auto' if you don't need to force a specific tool
Example fix
// before
{"tools": [{"name": "get_weather", ...}], "tool_choice": {"type": "tool", "name": "GetWeather"}}
// after
{"tools": [{"name": "get_weather", ...}], "tool_choice": {"type": "tool", "name": "get_weather"}} Defensive patterns
Strategy: validation
Validate before calling
names = {t.get("name") for t in tools if t.get("type") in ("custom", "function")}
if tool_choice.get("type") == "tool" and tool_choice.get("name") not in names:
raise ValueError("tool_choice.name must match a custom tool name") Type guard
def tool_choice_is_valid(tool_choice, tools) -> bool:
if tool_choice.get("type") != "tool": return True
return tool_choice.get("name") in {t.get("name") for t in tools} Try / catch
try: resp = client.messages.create(...)
except ValueError as e:
if 'tool_choice references tool' in str(e): fix_name_and_retry() Prevention
- Derive tool_choice.name from the tools array programmatically
- Remember built-in Anthropic tools can't be selected
When it happens
Trigger: POST /v1/messages with tool_choice={"type": "tool", "name": "get_weather"} where no tool named get_weather appears in the tools array; or tool_choice naming an Anthropic built-in like web_search_20250305.
Common situations: Typos or case mismatches between tool name and tool_choice name; assuming built-in Anthropic tools can be force-selected; frontend and backend tool definitions drifting out of sync.
Related errors
- tool_choice={tc_type!r} requires at least one custom tool; a
- thinking.budget_tokens must be >= 1024 (got {})
- thinking.budget_tokens is not allowed when thinking.type is
- thinking.display is not allowed when thinking.type is 'disab
- thinking.budget_tokens is not allowed when thinking.type is
AI-assisted analysis of sgl-project/sglang@0132848349 (2026-08-28).
Data as JSON: /api/errors/a285f074cb096dfc.
Report an issue: GitHub.