can1357/oh-my-pi · error

Tool ${toolCall.name} not found

Error message

Tool ${toolCall.name} not found

What it means

During argument validation of an assistant tool call, the resolved `tool` variable is undefined — the model emitted a toolCall for a name that is not registered on the agent/session. The validate() helper throws this error synchronously; with lenientArgValidation tools it is caught and degraded to a parse-error result, but for normal tools it surfaces. It exists so unregistered tool names fail explicitly instead of crashing on `tool.parameters` lookups.

Source

Thrown at packages/agent/src/agent-loop.ts:2253

		if (intentTracing) {
			const { intent, strippedArgs } = extractIntent(toolCall.arguments);
			argsForExecution = strippedArgs;
			if (intent) {
				toolCall.intent = intent;
			} else if (typeof tool?.intent === "function") {
				try {
					const derived = tool.intent(strippedArgs as never)?.trim();
					if (derived) {
						toolCall.intent = derived;
					}
				} catch {
					// intent function must never break tool execution
				}
			}
		}
		const validate = (args: Record<string, unknown>): Record<string, unknown> | undefined => {
			try {
				if (!tool) throw new Error(`Tool ${toolCall.name} not found`);
				return validateToolArguments(tool, { ...toolCall, arguments: args });
			} catch (validationError) {
				if (tool?.lenientArgValidation) {
					const fallback = { ...args };
					delete fallback.__parseError;
					delete fallback.__rawJson;
					return fallback;
				}
				entry.args = "__parseError" in args ? { __parseError: args.__parseError } : args;
				entry.validationErrorMessage =
					validationError instanceof Error ? validationError.message : String(validationError);
				return undefined;
			}
		};
		const effectiveArgs = validate(argsForExecution);
		if (effectiveArgs === undefined) continue;
		entry.args = effectiveArgs;
		if (!beforeToolCall || !tool) continue;

View on GitHub (pinned to 9690622007)

Solutions

  1. Log/inspect the offending toolCall.name and ensure a tool with that exact name is registered on the session before prompting
  2. If tools are conditionally filtered, keep previously-offered tools registered until their pending calls complete (or return a proper tool-result error instead of dropping the tool)
  3. For a resumed session, restore the same toolset that produced the recorded tool calls
  4. Mark the tool lenientArgValidation only if you intend graceful degradation — it does not fix a missing tool registration

Example fix

// before
defineTool(agent, { name: "read-file", ... }); // registered with a dash
// model calls "read_file" -> Tool read_file not found
// after
const tool = defineTool({ name: "read_file", ... });
agent.addTool(tool); // name matches what the prompt/model uses
Defensive patterns

Strategy: validation

Validate before calling

// Ensure every tool name the model can see is registered
for (const call of assistantMessage.content.filter(c => c.type === "toolCall")) {
  if (!session.getTools().some(t => t.name === call.name)) {
    console.warn(`model referenced unregistered tool: ${call.name}`);
  }
}

Type guard

function isToolNotFoundError(err: unknown, name?: string): err is Error {
  return err instanceof Error && err.message.startsWith("Tool ") && err.message.endsWith("not found")
    && (name === undefined || err.message.includes(name));
}

Try / catch

try {
  const args = validateToolArguments(tool, toolCall);
} catch (err) {
  if (isToolNotFoundError(err)) {
    return createErrorToolResult(toolCall, `Unknown tool: ${toolCall.name}`); // let the model recover
  }
  throw err;
}

Prevention

When it happens

Trigger: The message content contains a toolCall whose `name` does not match any tool in the session's tool registry, and validation of its arguments is attempted (e.g. during transcript repair / streaming argument validation where validate() runs on partially or fully parsed args).

Common situations: Model hallucinating a tool name not in the current toolset; tools removed or filtered (dialect/permission gating) between the call being emitted and executed; session resumed with a different tool configuration than when the call was recorded; typo in tool registration vs. prompt reference.

Related errors


AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31). Data as JSON: /api/errors/1995934286315384. Report an issue: GitHub.