vercel/ai · error · InvalidArgumentError
tool "${toolName}" contains an invalid caller.
Error message
tool "${toolName}" contains an invalid caller. What it means
Every entry in a toolCallers array must itself be the name of an existing tool that exposes a caller (experimental_getToolCaller must return a value). resolveToolCallerConfiguration throws this InvalidArgumentError when a caller string is not a string, does not name a defined tool, or names a tool without a configured caller.
Source
Thrown at packages/ai/src/generate-text/tool-caller-configuration.ts:66
if (!Array.isArray(callers)) {
throw new InvalidArgumentError({
parameter: 'experimental_toolCallers',
value: toolCallers,
message: `callers for tool "${toolName}" must be an array.`,
});
}
resolved[toolName] = callers.map(caller => {
if (caller === DIRECT_TOOL_CALL) {
return caller;
}
if (
typeof caller !== 'string' ||
!Object.prototype.hasOwnProperty.call(tools, caller) ||
experimental_getToolCaller(tools[caller]) == null
) {
throw new InvalidArgumentError({
parameter: 'experimental_toolCallers',
value: toolCallers,
message: `tool "${toolName}" contains an invalid caller.`,
});
}
return caller;
});
}
return resolved;
}
export function prepareToolsForToolCallers({
tools,
toolCallers,
}: {
tools: ToolSet | undefined;View on GitHub (pinned to 69428b1f8b)
Solutions
- Ensure each caller string names a tool present in `tools` that defines a tool caller implementation.
- Fix typos in the caller name.
- Add the caller tool to the tools map of the same call.
- Only mark caller-capable tools (e.g. agent tools with experimental tool caller support) as callers.
Example fix
// before
streamText({
tools: { summarize },
experimental_toolCallers: { summarize: ['summarizerAgent'] }, // summarizerAgent not in tools
});
// after
streamText({
tools: { summarize, summarizerAgent },
experimental_toolCallers: { summarize: ['summarizerAgent'] },
}); Defensive patterns
Strategy: validation
Validate before calling
function validateCallerEntries(tools: Record<string, unknown>, toolCallers: Record<string, string[]>) {
for (const [name, callers] of Object.entries(toolCallers)) {
for (const caller of callers) {
if (typeof caller !== 'string' || !(caller in tools)) {
throw new Error(`tool "${name}" references invalid caller "${String(caller)}"`);
}
}
}
} Type guard
function isKnownCaller<K extends string>(tools: Record<K, unknown>, caller: unknown): caller is K {
return typeof caller === 'string' && caller in tools;
} Try / catch
try {
await generateText({ tools, experimental_toolCallers, ... });
} catch (error) {
if (InvalidArgumentError.isInstance(error) && /invalid caller/.test(error.message)) {
console.error('Caller must be an existing caller-capable tool:', error.message);
} else throw error;
} Prevention
- Only list tools that both exist in `tools` and implement a tool caller (agent tools).
- Keep caller names in a shared const object with the tools map.
- Add a startup-time consistency test for your tool + caller configuration.
When it happens
Trigger: Passing `experimental_toolCallers: { myTool: ['notATool'] }` where 'notATool' is missing from tools, is a non-string value, or is a tool that has no getToolCaller implementation (not itself callable as a caller).
Common situations: Listing an agent/model tool that wasn't included in the tools map; listing a plain function tool that cannot act as a caller; typos in the caller name; circular or self references that are not caller-capable tools.
Related errors
- unknown tool "${toolName}".
- callers for tool "${toolName}" must be an array.
- Invalid argument for parameter output: Invalid output type.
- Chunking must be "word", "line", a RegExp, an Intl.Segmenter
- 'HarnessAgent: pass either `activeTools` or `inactiveTools`,
AI-assisted analysis of vercel/ai@69428b1f8b (2026-08-30).
Data as JSON: /api/errors/43e16f9f786fafd7.
Report an issue: GitHub.