windmill-labs/windmill · error
Unknown tool call: ${functionName}. Probably not in the corr
Error message
Unknown tool call: ${functionName}. Probably not in the correct mode, use the change_mode tool to switch to the correct mode. What it means
callTool looks up the requested function name among the tools registered for the CURRENT chat mode. If no tool matches, it throws this error hinting that the model is probably in the wrong mode and should call change_mode to switch. It signals a mode/toolset mismatch between what the model emitted and the active tool list.
Source
Thrown at frontend/src/lib/components/copilot/chat/shared.ts:717
tools,
functionName,
args,
workspace,
helpers,
toolCallbacks,
toolId
}: {
tools: Tool<T>[]
functionName: string
args: any
workspace: string
helpers: T
toolCallbacks: ToolCallbacks
toolId: string
}): Promise<string> {
const tool = tools.find((t) => t.def.function.name === functionName)
if (!tool) {
throw new Error(
`Unknown tool call: ${functionName}. Probably not in the correct mode, use the change_mode tool to switch to the correct mode.`
)
}
const result = await tool.fn({ args, workspace, helpers, toolCallbacks, toolId })
toolCompletionListener?.(functionName, args)
return result
}
type MaybePromise<T> = T | Promise<T>
/** A refused tool call: the row the user reads, and the result the model gets. A bare string
* is both at once. */
export type ToolRejection = string | { label: string; result: string }
function normalizeToolRejection(
rejection: ToolRejection | undefined
): { label: string; result: string } | undefined {
if (rejection === undefined) return undefinedView on GitHub (pinned to e474e8803c)
Solutions
- Follow the hint: have the model call the change_mode tool to switch to the mode that owns the tool, then retry the call.
- Verify the frontend/chat mode matches the user's intent (script vs flow vs app) before continuing the conversation.
- If the tool name looks right but fails, check for recent renames of the tool def and re-send with the current name.
- Restart the chat so the toolset registration and model state are consistent.
Example fix
// before (model in script mode calls flow tool)
{"name": "update_flow_value", ...} // -> Unknown tool call
// after
{"name": "change_mode", "arguments": {"new_mode": "flow"}}
then
{"name": "update_flow_value", ...} Defensive patterns
Strategy: try-catch
Validate before calling
const available = tools.map((t) => t.def.function.name)
if (!available.includes(functionName)) {
// ask the model to call change_mode first, or remap the name
return requestModeSwitch(knownAliasFor(functionName))
} Type guard
function isKnownTool<T extends { def: { function: { name: string } } }>(tools: T[], name: string): T | undefined {
return tools.find((t) => t.def.function.name === name)
} Try / catch
try {
result = await callTool({ functionName, tools, ... })
} catch (e) {
if (e instanceof Error && e.message.startsWith('Unknown tool call:')) {
// feed the message back to the model instructing a change_mode call, then retry
}
} Prevention
- Keep the tool list sent to the LLM in sync with the active chat mode.
- Register the change_mode tool in every mode's toolset so the model can recover itself.
- Validate tool names against the active toolset before forwarding model output.
- Alias deprecated/renamed tool names to their new definitions.
When it happens
Trigger: The model emitted a tool call whose function name exists only in another mode's toolset (e.g. an app-mode or flow-mode tool while the chat is in script mode), or a stale/renamed tool name was sent, and processToolCall passed it to callTool where tools.find returned undefined.
Common situations: User switches topics mid-chat (asks a flow question while in script mode) and the model guesses a flow tool name; the model hallucinates a tool name not in any toolset; frontend mode state drifted from the toolset that was registered in the LLM request.
Related errors
- AI response was empty
- AI response contained empty code block
- AI response did not contain valid code. Please try rephrasin
- An unexpected error occurred. Please try again.
- No flow helpers found
AI-assisted analysis of windmill-labs/windmill@e474e8803c (2026-09-03).
Data as JSON: /api/errors/e25b07a8c6f58aee.
Report an issue: GitHub.