AI SDK

"Model tried to call unavailable tool 'X'. Available tools: ..."

Last checked

The error

Model tried to call unavailable tool 'unknown'. Available tools: bash, edit, glob, grep, read, write.

Thrown as NoSuchToolError by the Vercel AI SDK (npm package ai). OpenCode prefixes it with "The arguments provided to the tool are invalid:" and, when no tools are loaded, the tail reads "No tools are available."

This is the Vercel AI SDK's NoSuchToolError. The model returned a tool call whose name is not in the tools object your app passed for that step, so the SDK refused to run it. The name is usually hallucinated (common with small local models), malformed, or a tool you removed mid-conversation. Fix: upgrade the ai package, keep the tool list short and stable, and handle the error so the model can retry instead of the turn crashing.

Why it happens

The AI SDK checks every tool call the model returns against the tools you registered for that step. If the name is not there, it raises NoSuchToolError and prints the requested name plus the full list it does have, which is why the message can be very long.

  1. The model invented the name. Small and quantized local models emit placeholders such as unknown or invalid, or guess a plausible tool. OpenCode users hit it constantly with Qwen models (issue #21090) and with phantom calls from Qwen via OpenRouter (issue #33618, open).
  2. The tool set changed mid-conversation. If you narrow tools with activeTools or rebuild the tools object per request, the model can still call a tool it saw earlier in history or a stale system prompt. Older SDKs also listed, and could run, inactive tools (vercel/ai issue #9141, fixed in ai 5.0.217 and 6.0.231).
  3. The call is malformed. Some models paste XML-style syntax into the name field, so the error shows a name like tool1" /> even though tool1 is listed. Left in history, that name can make Bedrock reject the next request (vercel/ai issue #9173).
  4. A step with no tools got a tool call. In OpenCode, compaction produced "Available tools: ." and ended the turn (issue #13317, closed without a fix).
  5. Context overflow. Past the model's real context window, tool definitions get cut off and the model starts guessing names.

The fix

  1. 1 Read the name in the quotes. A real tool you removed points to a stale tool set or prompt; unknown, invalid or an XML fragment points to the model.
  2. 2 Upgrade the SDK so activeTools filtering also applies to parsing and execution: npm install ai@latest (at least ai 5.0.217 on v5, ai 6.0.231 on v6).
  3. 3 Keep the tool list stable for the whole conversation and remove deleted tools from the system prompt and saved history.
  4. 4 Handle the error instead of crashing: add a repair function (experimental_repairToolCall in AI SDK 5 and 6, repairToolCall in v7) and check NoSuchToolError.isInstance(error).
  5. 5 For local models, pick one with reliable tool calling, raise the context length and register fewer tools.
  6. 6 In OpenCode, deny unneeded tools in the permission block of opencode.json; MCP tools accept wildcards such as "mymcp_*": "deny".
npm install ai@latest

Why small local models trigger it most

Smaller and quantized models are worse at copying an exact name from a long tool list, so they fall back to generic or half-remembered names. Dozens of MCP tools add thousands of tokens of definitions, and a model near its context limit loses track of which names are real.

The error then feeds itself: each failure adds the full tool list to the context again. One OpenCode user with about 130 MCP tools reported thousands of wasted tokens per error (issue #41047, closed as stale). Fewer tools and a model with dependable tool calling break the loop.

Handling it in AI SDK code

generateText throws NoSuchToolError, so wrap it in try/catch; streamText emits it as an error part. A repair function can intercept it first. Returning null declines the repair:

import { generateText, NoSuchToolError } from 'ai';

const result = await generateText({
  model,
  tools,
  // AI SDK 5 and 6: experimental_repairToolCall; v7: repairToolCall
  experimental_repairToolCall: async ({ toolCall, error }) => {
    if (NoSuchToolError.isInstance(error)) {
      console.warn('Unknown tool:', toolCall.toolName);
    }
    return null;
  },
  prompt,
});

Still failing?

  • Log toolCall.toolName on every failure: if the same real name keeps appearing, your prompt, history or MCP config still advertises it.
  • Check the name for quotes, slashes or dollar signs, which point to a malformed call that can break the next provider request.
  • Run the same prompt on a different model; if the error disappears, the model's tool calling is the problem.

Related errors

Full guide"Does Not Support Tools" in Ollama: Which Models Actually Work

Hit a different error?

Paste any agent error and get the cause and fix in seconds.

Open the decoder

Frequently asked questions

Is this an OpenCode bug or an AI SDK bug?

The text comes from the AI SDK's NoSuchToolError, and OpenCode is built on the AI SDK. The trigger is almost always the model asking for an unregistered name. OpenCode adds the prefix "The arguments provided to the tool are invalid:".

Why does the error list tools I disabled?

Before ai 5.0.217 and 6.0.231, activeTools only filtered what was sent to the provider, so the error listed inactive tools (vercel/ai issue #9141). Upgrading fixes it.

Can I stop the long tool list wasting tokens?

In your own code, catch NoSuchToolError and return a short message. In OpenCode the request to shorten it (issue #41047) was closed without a change, so register fewer tools.

Stop firefighting agent errors

Decoding errors one at a time is the manual version of what BetterClaw automates. Run your agents on a no-code AI agent platform with managed models, retries and config validation built in.

Free plan available · Pro $49/mo · BYOK · 7-day money-back guarantee