vercel/ai · error · InvalidArgumentError
unknown tool "${toolName}".
Error message
unknown tool "${toolName}". What it means
When resolving `experimental_toolCallers`, every key in the toolCallers map must correspond to a tool actually defined in the request's `tools`. resolveToolCallerConfiguration throws this InvalidArgumentError if a toolCallers key references a tool name that does not exist (own-property check, so inherited names like 'constructor' don't count). This is an upfront configuration validation to fail fast instead of silently ignoring routing rules.
Source
Thrown at packages/ai/src/generate-text/tool-caller-configuration.ts:41
export type ResolvedToolCallers = Record<string, ReadonlyArray<string>>;
export function resolveToolCallerConfiguration<TOOLS extends ToolSet>({
tools,
toolCallers,
}: {
tools: TOOLS | undefined;
toolCallers: Experimental_ToolCallers<TOOLS> | undefined;
}): ResolvedToolCallers | undefined {
if (tools == null || toolCallers == null) {
return undefined;
}
const resolved: ResolvedToolCallers = {};
for (const [toolName, callers] of Object.entries(toolCallers)) {
if (!Object.prototype.hasOwnProperty.call(tools, toolName)) {
throw new InvalidArgumentError({
parameter: 'experimental_toolCallers',
value: toolCallers,
message: `unknown tool "${toolName}".`,
});
}
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;
}View on GitHub (pinned to 69428b1f8b)
Solutions
- Make every key of experimental_toolCallers exactly match a key in the tools object of the same call.
- Fix typos/renames in the toolCallers map (or in tools).
- Derive the toolCallers keys programmatically from the same object used for tools.
- Remove stale entries for tools no longer passed in this request.
Example fix
// before
streamText({ model, tools: { weather }, experimental_toolCallers: { wether: ['weatherAgent'] } });
// after
streamText({ model, tools: { weather }, experimental_toolCallers: { weather: ['weatherAgent'] } }); Defensive patterns
Strategy: validation
Validate before calling
function validateToolCallers(tools: Record<string, unknown>, toolCallers: Record<string, unknown>) {
for (const name of Object.keys(toolCallers)) {
if (!Object.prototype.hasOwnProperty.call(tools, name)) {
throw new Error(`experimental_toolCallers references unknown tool "${name}"`);
}
}
} Type guard
function allCallersKnown<K extends string>(
tools: Record<K, unknown>,
toolCallers: Partial<Record<K, unknown>>
): toolCallers is Partial<Record<K, unknown>> {
return Object.keys(toolCallers).every(k => k in tools);
} Try / catch
try {
await generateText({ tools, experimental_toolCallers, ... });
} catch (error) {
if (InvalidArgumentError.isInstance(error) && error.parameter === 'experimental_toolCallers') {
console.error('Tool caller config error:', error.message);
} else throw error;
} Prevention
- Derive toolCallers keys from the same typed object as tools so TypeScript catches renames.
- Keep tool definitions and their caller routing co-located in one module.
- Avoid stringly-typed tool names; use const objects/satisfies for keys.
When it happens
Trigger: Passing `experimental_toolCallers: { myTool: [...] }` to streamText/generateText where 'myTool' is misspelled, was renamed, or was never added to the `tools` object of the same call.
Common situations: Typo or renamed tool after refactoring; defining toolCallers at call sites that share a config object but have different tool sets; dynamically built tool maps where a tool was conditionally omitted; case-sensitivity mismatches in tool names.
Related errors
- callers for tool "${toolName}" must be an array.
- tool "${toolName}" contains an invalid caller.
- 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/0ae9ce9130e24e93.
Report an issue: GitHub.