vercel/ai · error · NoSuchToolError
Model tried to call unavailable tool '${toolName}'. No tools
Error message
Model tried to call unavailable tool '${toolName}'. No tools are available. What it means
NoSuchToolError thrown when the model emitted a tool call for a tool name that is not in the `tools` map passed to generateText/generateObject, and no tools at all were provided. The SDK cannot resolve an input schema or execute the call, so parsing the tool call fails. It guards against hallucinated tool names.
Source
Thrown at packages/ai/src/generate-text/parse-tool-call.ts:44
}: {
toolCall: LanguageModelV4ToolCall;
tools: TOOLS | undefined;
repairToolCall: ToolCallRepairFunction<TOOLS> | undefined;
refineToolInput?: ToolInputRefinement<TOOLS> | undefined;
instructions: Instructions | undefined;
messages: ModelMessage[];
}): Promise<TypedToolCall<TOOLS>> {
try {
if (tools == null) {
// provider-executed dynamic tools are not part of our list of tools:
if (toolCall.providerExecuted && toolCall.dynamic) {
return await refineParsedToolCallInput({
toolCall: await parseProviderExecutedDynamicToolCall(toolCall),
refineToolInput,
});
}
throw new NoSuchToolError({ toolName: toolCall.toolName });
}
try {
return await refineParsedToolCallInput({
toolCall: await doParseToolCall({ toolCall, tools }),
refineToolInput,
});
} catch (error) {
if (
repairToolCall == null ||
!(
NoSuchToolError.isInstance(error) ||
InvalidToolInputError.isInstance(error)
)
) {
throw error;
}
View on GitHub (pinned to 69428b1f8b)
Solutions
- Pass the `tools` object to the generateText/streamText call that receives this response.
- If the model should not call tools, remove tool-calling instructions from the system prompt or use a model/endpoint without tool definitions.
- Use `experimental_repairToolCall` or catch NoSuchToolError (NoSuchToolError.isInstance) and skip/reprompt the model.
Example fix
// before
const { text } = await generateText({ model, prompt });
// after
const { text } = await generateText({ model, prompt, tools: { weather } }); Defensive patterns
Strategy: validation
Validate before calling
if (!tools || Object.keys(tools).length === 0) {
throw new Error('generateText requires a non-empty tools map for this prompt');
} Type guard
function hasTools<T extends Record<string, unknown>>(t?: T): t is T {
return t != null && Object.keys(t).length > 0;
} Try / catch
try {
await generateText({ model, prompt, tools });
} catch (e) {
if (NoSuchToolError.isInstance(e)) {
// re-prompt with the list of available tools
} else throw e;
} Prevention
- Always pass the tools object wherever the system prompt mentions tools.
- Centralize tool definitions so every agent step shares them.
- Write a test that runs a tool-calling prompt against each call site.
When it happens
Trigger: Calling generateText/streamText with no `tools` option while the model (trained or prompted to use tools) returns a tool_call; or the tools map is empty `{}` at the parse site.
Common situations: Forgetting to pass tools on one step/agent path while the system prompt still mentions them; using a different model endpoint that injects tool definitions; refactoring so tools are conditionally omitted; model hallucinating tools when tools: undefined.
Related errors
- Model tried to call unavailable tool '${toolName}'. Availabl
- Invalid argument for parameter model: model ${model.provider
- Unsupported output: ${_exhaustiveCheck}
- Invalid argument for parameter output: Invalid output type.
- Model could not be resolved
AI-assisted analysis of vercel/ai@69428b1f8b (2026-08-30).
Data as JSON: /api/errors/471ba160c6a50a1b.
Report an issue: GitHub.