{"record":{"id":"f7ed4fcd35000970","repo":"ZhuLinsen/daily_stock_analysis","slug":"tool-name-not-found-in-registry-available-s","errorCode":null,"errorMessage":"Tool '{name}' not found in registry. Available: {self.list_names()}","messagePattern":"Tool '(.+?)' not found in registry\\. Available: (.+?)","errorType":"exception","errorClass":"KeyError","httpStatus":null,"severity":"error","filePath":"src/agent/tools/registry.py","lineNumber":290,"sourceCode":"                    \"code\": \"stock_scope_parameter_missing\",\n                    \"message\": \"Tool declares stock scope but has no stock_code parameter.\",\n                })\n        return issues\n\n    # ----- Execution -----\n\n    def execute(self, name: str, **kwargs) -> Any:\n        \"\"\"Execute a registered tool by name.\n\n        Returns the result as a JSON-serializable value.\n        Raises ``KeyError`` if tool not found.\n        Raises the handler's exception on execution failure.\n\n        Tool names must match the registry exactly.\n        \"\"\"\n        tool_def = self.resolve(name)\n        if tool_def is None:\n            raise KeyError(f\"Tool '{name}' not found in registry. Available: {self.list_names()}\")\n\n        return tool_def.handler(**kwargs)\n\n\n# ============================================================\n# @tool decorator\n# ============================================================\n\n# Global default registry (singleton pattern)\n_default_registry: Optional[ToolRegistry] = None\n\n\ndef get_default_registry() -> ToolRegistry:\n    \"\"\"Get or create the global default ToolRegistry.\"\"\"\n    global _default_registry\n    if _default_registry is None:\n        _default_registry = ToolRegistry()\n    return _default_registry","sourceCodeStart":272,"sourceCodeEnd":308,"githubUrl":"https://github.com/ZhuLinsen/daily_stock_analysis/blob/5159bd72e8373d215492dff122acc9d389e219c9/src/agent/tools/registry.py#L272-L308","documentation":"KeyError raised by ToolRegistry.execute when resolve(name) returns None — i.e. no tool is registered under that exact name in this registry instance. The message lists all registered names to make the mismatch obvious. This fires before any handler runs, so it is purely a name-resolution failure, not a tool execution failure.","triggerScenarios":"registry.execute('fetch_quote', ...) when only e.g. 'get_quote' is registered; calling a tool on a fresh/default registry that was never populated; case or underscore mismatches ('websearch' vs 'web_search'); calling after a registry reset where _default_registry was rebuilt empty.","commonSituations":"An LLM hallucinating a tool name not in the advertised schema; typos in dynamic dispatch code; tools registered on a custom registry instance while the caller uses the global default (or vice versa); tool renamed in a newer version but the caller still uses the old name.","solutions":["Check the names in the error's 'Available:' list and call execute with one of them exactly.","If the tool genuinely should exist, verify it was registered (via @tool decorator or registry.register) on the SAME registry instance you are executing against.","For LLM-driven calls, constrain the model's tool schema to registry.list_names() and retry or reject unknown names instead of executing blindly."],"exampleFix":"# before\nresult = registry.execute(\"fetch_quote\", symbol=\"AAPL\")  # KeyError\n\n# after\nresult = registry.execute(\"get_quote\", symbol=\"AAPL\")  # name from registry.list_names()","handlingStrategy":"type-guard","validationCode":"names = set(registry.list_names())\nif tool_name not in names:\n    raise ValueError(f\"unknown tool {tool_name!r}; known: {sorted(names)}\")","typeGuard":"def is_registered_tool(registry, name: str) -> bool:\n    return registry.resolve(name) is not None","tryCatchPattern":"try:\n    result = registry.execute(name, **kwargs)\nexcept KeyError as e:\n    # message lists available names; fall back to a corrective action for LLM callers\n    return {\"error\": \"unknown_tool\", \"available\": registry.list_names()}","preventionTips":["Filter LLM-requested tool calls against registry.list_names() before executing.","Register tools on the same registry instance you execute against.","Pin tool names in one constant module so renames propagate."],"tags":["agent","tool-registry","key-error","dispatch"],"backgroundTag":null,"analyzedSha":"5159bd72e8373d215492dff122acc9d389e219c9","analyzedAt":"2026-08-15T01:59:36.292Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}