shareAI-lab/learn-claude-code · error · GoalError
unknown tool '{name}'
Error message
unknown tool '{name}' What it means
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.
Source
Thrown at s17_goal_loop/code.py:807
path = self._safe_path(str(arguments["path"]))
old_text = str(arguments["old_text"])
new_text = str(arguments["new_text"])
content = path.read_text(encoding="utf-8")
count = content.count(old_text)
if count != 1:
return f"Error: Expected 1 occurrence, found {count}"
path.write_text(content.replace(old_text, new_text), encoding="utf-8")
return f"Edited {path.relative_to(self.workdir)}"
if name == "glob":
matches = [
match
for match in glob.glob(str(arguments["pattern"]), root_dir=self.workdir)
if (self.workdir / match).resolve().is_relative_to(self.workdir)
]
return "\n".join(matches[:200]) if matches else "(no matches)"
raise GoalError(f"unknown tool '{name}'")
def make_live_session(workdir: Path) -> AgentSession:
try:
from anthropic import Anthropic
from dotenv import load_dotenv
except ImportError as error:
raise GoalError(
"Install dependencies first: pip install -r requirements.txt"
) from error
load_dotenv(override=True)
model = os.getenv("MODEL_ID")
if not model:
raise GoalError("MODEL_ID is required in the environment or .env")
evaluator_model = (
os.getenv("GOAL_EVALUATOR_MODEL_ID")
or os.getenv("ANTHROPIC_DEFAULT_HAIKU_MODEL")View on GitHub (pinned to 985456f4ad)
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
Example fix
# before
# tool sent to model includes {"name": "list_dir", ...} but _run_query has no branch for it
# after
# either rename the definition to the implemented tool:
tools = [{"name": "glob", "description": "list files matching a pattern", ...}] Defensive patterns
Strategy: retry
Validate before calling
IMPLEMENTED_TOOLS = {"bash", "read", "write", "edit", "glob"}
tools = [t for t in advertised_tools if t["name"] in IMPLEMENTED_TOOLS]
assert len(tools) == len(advertised_tools), "tool list diverges from dispatcher" Type guard
def is_known_tool(name: object) -> bool:
return isinstance(name, str) and name in {"bash", "read", "write", "edit", "glob"} Try / catch
try:
await session.submit(query)
except GoalError as error:
if "unknown tool" in str(error):
result = await session.submit(query) # retry; model self-corrects on replay
else:
raise Prevention
- 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
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- goal evaluator returned invalid JSON
- goal evaluator must return a JSON object
- goal evaluator response requires boolean 'ok'
- goal evaluator response requires non-empty 'reason'
- goal evaluator 'impossible' must be boolean
AI-assisted analysis of shareAI-lab/learn-claude-code@985456f4ad (2026-08-14).
Data as JSON: /api/errors/40bfc26ac4055491.
Report an issue: GitHub.