{"record":{"id":"e1ef3d76d03c9f13","repo":"BerriAI/litellm","slug":"tool-search-tool-must-have-a-valid-name","errorCode":null,"errorMessage":"Tool search tool must have a valid name","messagePattern":"Tool search tool must have a valid name","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"litellm/llms/anthropic/chat/transformation.py","lineNumber":735,"sourceCode":"                if k != \"type\" and k != \"name\":\n                    additional_tool_params[k] = v\n\n            returned_tool = AnthropicHostedTools(\n                type=tool[\"type\"],\n                name=function_name,\n                **additional_tool_params,\n            )\n        elif tool[\"type\"] == \"url\":  # mcp server tool\n            mcp_server = AnthropicMcpServerTool(**tool)\n        elif tool[\"type\"] == \"mcp\":\n            mcp_server = self._map_openai_mcp_server_tool(cast(OpenAIMcpServerTool, tool))\n        elif tool[\"type\"] == \"tool_search_tool_regex_20251119\":\n            # Tool search tool using regex\n            from litellm.types.llms.anthropic import AnthropicToolSearchToolRegex\n\n            tool_name_obj = tool.get(\"name\", \"tool_search_tool_regex\")\n            if not isinstance(tool_name_obj, str):\n                raise ValueError(\"Tool search tool must have a valid name\")\n            tool_name = tool_name_obj\n            returned_tool = AnthropicToolSearchToolRegex(\n                type=\"tool_search_tool_regex_20251119\",\n                name=tool_name,\n            )\n        elif tool[\"type\"] == \"tool_search_tool_bm25_20251119\":\n            # Tool search tool using BM25\n            from litellm.types.llms.anthropic import AnthropicToolSearchToolBM25\n\n            tool_name_obj = tool.get(\"name\", \"tool_search_tool_bm25\")\n            if not isinstance(tool_name_obj, str):\n                raise ValueError(\"Tool search tool must have a valid name\")\n            tool_name = tool_name_obj\n            returned_tool = AnthropicToolSearchToolBM25(\n                type=\"tool_search_tool_bm25_20251119\",\n                name=tool_name,\n            )\n        elif tool[\"type\"] == ANTHROPIC_ADVISOR_TOOL_TYPE:","sourceCodeStart":717,"sourceCodeEnd":753,"githubUrl":"https://github.com/BerriAI/litellm/blob/6c2dcb801bf2b75c18f1bb24140e7cf57465cc4d/litellm/llms/anthropic/chat/transformation.py#L717-L753","documentation":"For the regex-based tool-search tool (type 'tool_search_tool_regex_20251119'), LiteLLM reads tool.get('name', 'tool_search_tool_regex') and requires the result to be a string. A non-string name (int, dict, None explicitly set) triggers this ValueError during request transformation.","triggerScenarios":"Passing {'type': 'tool_search_tool_regex_20251119', 'name': 123} or 'name': {'value': 'x'} — a name key present but not a string. Omitting name entirely is fine (default applied); only a wrong-typed value fails.","commonSituations":"Tool dicts produced by serialization layers that coerce values (e.g. YAML config turning a quoted key into a mapping); LLM-generated tool JSON with nested name objects; programmatic construction bugs.","solutions":["Set 'name' to a plain string (or remove the key to use the default 'tool_search_tool_regex').","Check the exact spelling: only the type key must equal 'tool_search_tool_regex_20251119'.","Validate types in config loading if tools come from YAML/JSON files where nesting is easy to get wrong."],"exampleFix":"# before\n{\"type\": \"tool_search_tool_regex_20251119\", \"name\": {\"first\": \"x\"}}\n\n# after\n{\"type\": \"tool_search_tool_regex_20251119\", \"name\": \"tool_search_tool_regex\"}\n# or simply omit 'name' entirely","handlingStrategy":"type-guard","validationCode":"if \"name\" in tool and not isinstance(tool[\"name\"], str):\n    del tool[\"name\"]  # let LiteLLM apply the default\n# or: tool[\"name\"] = str(tool[\"name\"]) if errors acceptable","typeGuard":"def is_valid_tool_search_tool(tool) -> bool:\n    if tool.get(\"type\") not in (\"tool_search_tool_regex_20251119\", \"tool_search_tool_bm25_20251119\"):\n        return True  # not this tool kind\n    name = tool.get(\"name\")\n    return name is None or isinstance(name, str)","tryCatchPattern":null,"preventionTips":["Omit 'name' unless you need to override it; the default is correct.","Validate config files (YAML/JSON) with a schema where name must be a string."],"tags":["anthropic","tools","tool-search","validation"],"backgroundTag":null,"analyzedSha":"6c2dcb801bf2b75c18f1bb24140e7cf57465cc4d","analyzedAt":"2026-08-15T07:12:03.035Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}