{"record":{"id":"40bfc26ac4055491","repo":"shareAI-lab/learn-claude-code","slug":"unknown-tool-name","errorCode":null,"errorMessage":"unknown tool '{name}'","messagePattern":"unknown tool '(.+?)'","errorType":"validation","errorClass":"GoalError","httpStatus":null,"severity":"error","filePath":"s17_goal_loop/code.py","lineNumber":807,"sourceCode":"            path = self._safe_path(str(arguments[\"path\"]))\n            old_text = str(arguments[\"old_text\"])\n            new_text = str(arguments[\"new_text\"])\n            content = path.read_text(encoding=\"utf-8\")\n            count = content.count(old_text)\n            if count != 1:\n                return f\"Error: Expected 1 occurrence, found {count}\"\n            path.write_text(content.replace(old_text, new_text), encoding=\"utf-8\")\n            return f\"Edited {path.relative_to(self.workdir)}\"\n\n        if name == \"glob\":\n            matches = [\n                match\n                for match in glob.glob(str(arguments[\"pattern\"]), root_dir=self.workdir)\n                if (self.workdir / match).resolve().is_relative_to(self.workdir)\n            ]\n            return \"\\n\".join(matches[:200]) if matches else \"(no matches)\"\n\n        raise GoalError(f\"unknown tool '{name}'\")\n\n\ndef make_live_session(workdir: Path) -> AgentSession:\n    try:\n        from anthropic import Anthropic\n        from dotenv import load_dotenv\n    except ImportError as error:\n        raise GoalError(\n            \"Install dependencies first: pip install -r requirements.txt\"\n        ) from error\n\n    load_dotenv(override=True)\n    model = os.getenv(\"MODEL_ID\")\n    if not model:\n        raise GoalError(\"MODEL_ID is required in the environment or .env\")\n    evaluator_model = (\n        os.getenv(\"GOAL_EVALUATOR_MODEL_ID\")\n        or os.getenv(\"ANTHROPIC_DEFAULT_HAIKU_MODEL\")","sourceCodeStart":789,"sourceCodeEnd":825,"githubUrl":"https://github.com/shareAI-lab/learn-claude-code/blob/985456f4adea6f4df8fbad4112245dbd97444eae/s17_goal_loop/code.py#L789-L825","documentation":"AgentSession._run_tool dispatched a tool name that matches none of the implemented tools (bash, read, write, edit, glob, ...), so it raises GoalError(f\"unknown tool '{name}'\") at s17_goal_loop/code.py:807. The tool registry is a closed set of if-branches; any other name falls through to this error.","triggerScenarios":"The model emits a tool_use block with a name like 'grep', 'list_files', or a hallucinated tool not in the session's tool list; tools advertised to the model diverge from the ones implemented in _run_tool; a newer client sends a tool name this older code does not know.","commonSituations":"Tool schema sent to the model includes tools that were later renamed or removed from _run_tool; model hallucinating a tool name mid-run; version skew between the tool definitions and the dispatcher after an edit.","solutions":["Align the tool definitions passed to the model with the branches in _run_tool (same names, no extras)","If the model hallucinates, strengthen the tool descriptions/system prompt so only defined tools are used","Wrap the session loop in try/except GoalError and retry; a retry usually corrects the tool choice","Add a matching branch (or an alias) in _run_tool if the tool is genuinely wanted"],"exampleFix":"# before\n# tool sent to model includes {\"name\": \"list_dir\", ...} but _run_query has no branch for it\n\n# after\n# either rename the definition to the implemented tool:\ntools = [{\"name\": \"glob\", \"description\": \"list files matching a pattern\", ...}]","handlingStrategy":"retry","validationCode":"IMPLEMENTED_TOOLS = {\"bash\", \"read\", \"write\", \"edit\", \"glob\"}\ntools = [t for t in advertised_tools if t[\"name\"] in IMPLEMENTED_TOOLS]\nassert len(tools) == len(advertised_tools), \"tool list diverges from dispatcher\"","typeGuard":"def is_known_tool(name: object) -> bool:\n    return isinstance(name, str) and name in {\"bash\", \"read\", \"write\", \"edit\", \"glob\"}","tryCatchPattern":"try:\n    await session.submit(query)\nexcept GoalError as error:\n    if \"unknown tool\" in str(error):\n        result = await session.submit(query)  # retry; model self-corrects on replay\n    else:\n        raise","preventionTips":["Keep the tool definitions sent to the model in lockstep with _run_query's branches","Name tools exactly in definitions and dispatcher; avoid renames on one side only","Feed the 'unknown tool' message back to the agent so it picks a defined tool"],"tags":["goal-loop","tools","dispatch","llm"],"backgroundTag":null,"analyzedSha":"985456f4adea6f4df8fbad4112245dbd97444eae","analyzedAt":"2026-08-14T22:02:26.028Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}