vercel/ai · error
Tool "${toolCall.toolName}" not found
Error message
Tool "${toolCall.toolName}" not found What it means
executeTool looks up the requested tool by name in the provided tools map and throws when no tool with that name is registered. This happens when the model emitted a tool call that is not part of the tools passed to the workflow agent run.
Source
Thrown at packages/workflow/src/workflow-agent.ts:2949
function getToolCallbackMessages(
messages: LanguageModelV4Prompt,
): ModelMessage[] {
const withoutAssistantToolCall =
messages.at(-1)?.role === 'assistant' ? messages.slice(0, -1) : messages;
return withoutAssistantToolCall as unknown as ModelMessage[];
}
async function executeTool(
toolCall: { toolCallId: string; toolName: string; input: unknown },
tools: ToolSet,
messages: LanguageModelV4Prompt,
context?: unknown,
download?: DownloadFunction,
sandbox?: SandboxSession,
): Promise<WorkflowToolExecutionResult> {
const tool = tools[toolCall.toolName];
if (!tool) throw new Error(`Tool "${toolCall.toolName}" not found`);
if (typeof tool.execute !== 'function') {
throw new Error(
`Tool "${toolCall.toolName}" does not have an execute function. ` +
`Client-side tools should be filtered before calling executeTool.`,
);
}
// Input is already parsed and validated by streamModelCall's parseToolCall
const parsedInput = toolCall.input;
let toolResult: unknown;
try {
// Extract execute function to avoid binding `this` to the tool object.
// If we called `tool.execute(...)` directly, JavaScript would bind `this`
// to `tool`, which contains non-serializable properties like `inputSchema`.
// When the execute function is a workflow step (marked with 'use step'),
// the step system captures `this` for serialization, causing failures.
const { execute } = tool;
toolResult = await execute(parsedInput, {View on GitHub (pinned to 69428b1f8b)
Solutions
- Ensure every tool the model may call is present in the `tools` map passed to the agent/workflow step.
- Log toolCall.toolName and compare against Object.keys(tools) to find the mismatch.
- Filter invalid tool calls out of the prompt before execution (client-side tools are handled separately).
- Sync tool definitions between client and server if they are defined in two places.
Example fix
// before
await executeTool({ toolCall, tools: { getWeather } }); // model called 'search'
// after
await executeTool({ toolCall, tools: { getWeather, search } }); Defensive patterns
Strategy: validation
Validate before calling
if (!tools[toolCall.toolName]) {
throw new Error(`Tool "${toolCall.toolName}" is not registered; available: ${Object.keys(tools).join(', ')}`);
} Type guard
function isRegisteredTool(tools: Record<string, unknown>, name: string) {
return Object.prototype.hasOwnProperty.call(tools, name);
} Try / catch
try {
await executeTool({ toolCall, tools });
} catch (e) {
if (e instanceof Error && e.message.endsWith('not found')) {
console.error(`Unknown tool ${toolCall.toolName}; known: ${Object.keys(tools)}`);
// append tool-result error message to the conversation instead of crashing
} else throw e;
} Prevention
- Keep client and server tool registries in sync from a single shared definition module.
- Log available tool names when configuring the agent.
- Filter model tool calls against the registry before executing.
- Add tests that simulate model calls for every registered tool.
When it happens
Trigger: The model emits a tool call whose toolName is not present in the `tools` object passed to executeTool / the agent step; stale tool registry after changing tools; tool name mismatch between model configuration and execution context.
Common situations: Renaming a tool on the client but not the agent definition; multi-step conversations where earlier tool definitions were removed; passing a subset of tools to executeTool; typos in tool names.
Related errors
- Not implemented
- Tool "${toolCall.toolName}" does not have an execute functio
- [WorkflowAgent] Provider-executed tool "${toolCall.toolName}
- The ${model.provider} model "${model.modelId}" does not supp
- unknown tool "${toolName}".
AI-assisted analysis of vercel/ai@69428b1f8b (2026-08-30).
Data as JSON: /api/errors/37b6c44379a47418.
Report an issue: GitHub.