{"record":{"id":"7348b28ff98725a8","repo":"oraios/serena","slug":"invalid-tool-name-tool-name-caller-context-for","errorCode":null,"errorMessage":"Invalid tool name: {tool_name}{caller_context_for_logging}","messagePattern":"Invalid tool name: (.+?)(.+?)","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"src/serena/tools/tools_base.py","lineNumber":689,"sourceCode":"                tools = self.get_tool_classes_default_enabled()\n\n        tool_dict: dict[str, type[Tool] | Tool] = {}\n        for tool_class in tools:\n            tool_dict[tool_class.get_name_from_cls()] = tool_class\n        for tool_name in sorted(tool_dict.keys()):\n            tool_class = tool_dict[tool_name]\n            print(f\" * `{tool_name}`: {tool_class.get_tool_description().strip()}\")\n\n    def is_valid_tool_name(self, tool_name: str) -> bool:\n        return tool_name in self._tool_dict\n\n    def check_valid_tool_name(self, tool_name: str, caller_context_for_logging: str = \"\") -> bool:\n        \"\"\"Returns True if the tool name is valid, False if it is deleted, and raises ValueError if it is invalid.\"\"\"\n        if self.is_deleted_tool_name(tool_name):\n            log.warning(f\"Tool name is deleted: {tool_name}{caller_context_for_logging}\")\n            return False\n        if not self.is_valid_tool_name(tool_name):\n            raise ValueError(f\"Invalid tool name: {tool_name}{caller_context_for_logging}\")\n        return True\n\n    def is_deleted_tool_name(self, tool_name: str) -> bool:\n        return tool_name in self._deleted_tools\n","sourceCodeStart":671,"sourceCodeEnd":694,"githubUrl":"https://github.com/oraios/serena/blob/7fcbca7e62555ec2287ddb2f083caee805848ea6/src/serena/tools/tools_base.py#L671-L694","documentation":"Tool.check_valid_tool_name validates a tool name before use: names in the deleted-tools set return False (logged warning), while names that are not valid (not registered and not known) raise ValueError. It is called from Tool.apply to reject calls to tools that do not exist in the current registry.","triggerScenarios":"Calling apply (or check_valid_tool_name directly) with a tool_name that is neither a deleted name nor a valid registered tool name — typically a typo or a tool from another Serena version/context.","commonSituations":"LLM agent hallucinating a tool name; client caches stale tool lists after server config changed; renamed tools between versions; requesting context-inactive tools.","solutions":["Verify the tool name against the list exposed to the client (tools/list or registry listing) and fix the name","Check if the tool was renamed/deleted in the current Serena version and use the new name","Ensure the active tool context/_mode includes the tool before calling it","Catch ValueError and return a helpful message to the agent listing valid tools"],"exampleFix":"// before\nif registry.check_valid_tool_name(tool_name):\n    apply_tool(tool_name)\n// after\ntry:\n    if registry.check_valid_tool_name(tool_name):\n        apply_tool(tool_name)\nexcept ValueError:\n    log.warning(f\"Unknown tool {tool_name}; valid: {registry.get_all_tool_names()}\")","handlingStrategy":"validation","validationCode":"valid = registry.check_valid_tool_name(tool_name, caller_context_for_logging=\" from my_client\")\nif valid:\n    tool.apply(...)","typeGuard":"def is_valid_tool(registry, name: str) -> bool:\n    try:\n        return registry.check_valid_tool_name(name)\n    except ValueError:\n        return False","tryCatchPattern":null,"preventionTips":["Refresh the client's tool list after server config changes instead of caching","Validate tool names against the exposed tools/list before dispatching agent calls","Log the deleted-tool warning path so renamed tools are easy to spot"],"tags":["python","tool-registry","valueerror","mcp"],"backgroundTag":"unknown-identifier","analyzedSha":"7fcbca7e62555ec2287ddb2f083caee805848ea6","analyzedAt":"2026-08-29T00:04:09.619Z","schemaVersion":2},"datasetVersion":"2026-08-29T02:17:18.158Z"}