{"record":{"id":"2999d1c4ac9c5761","repo":"FlowiseAI/Flowise","slug":"tool-call-name-not-found","errorCode":null,"errorMessage":"Tool ${call.name} not found.","messagePattern":"Tool (.+?) not found\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/components/nodes/sequentialagents/Agent/Agent.ts","lineNumber":1023,"sourceCode":"\n        if (message._getType() !== 'ai') {\n            throw new Error('ToolNode only accepts AIMessages as input.')\n        }\n\n        // Extract all properties except messages for IStateWithMessages\n        const { messages: _, ...inputWithoutMessages } = Array.isArray(input) ? { messages: input } : input\n        const ChannelsWithoutMessages = {\n            chatId: this.options.chatId,\n            sessionId: this.options.sessionId,\n            input: this.inputQuery,\n            state: inputWithoutMessages\n        }\n\n        const outputs = await Promise.all(\n            (message as AIMessage).tool_calls?.map(async (call) => {\n                const tool = this.tools.find((tool) => tool.name === call.name)\n                if (tool === undefined) {\n                    throw new Error(`Tool ${call.name} not found.`)\n                }\n                if (tool && (tool as any).setFlowObject) {\n                    // @ts-ignore\n                    tool.setFlowObject(ChannelsWithoutMessages)\n                }\n                let output = await tool.invoke(call.args, config)\n                let sourceDocuments: Document[] = []\n                let artifacts = []\n\n                if (output?.includes(SOURCE_DOCUMENTS_PREFIX)) {\n                    const outputArray = output.split(SOURCE_DOCUMENTS_PREFIX)\n                    output = outputArray[0]\n                    const docs = outputArray[1]\n                    try {\n                        sourceDocuments = JSON.parse(docs)\n                    } catch (e) {\n                        console.error('Error parsing source documents from tool')\n                    }","sourceCodeStart":1005,"sourceCodeEnd":1041,"githubUrl":"https://github.com/FlowiseAI/Flowise/blob/abe4a8601a058047b350c260676826e21dd14101/packages/components/nodes/sequentialagents/Agent/Agent.ts#L1005-L1041","documentation":"For each `tool_call` on the incoming AIMessage, ToolNode looks up `this.tools.find(t => t.name === call.name)`. If the model called a tool name that is not registered in the ToolNode's `tools` array, lookup returns undefined and the node throws. The error names the missing tool so you can see what the model asked for.","triggerScenarios":"The AIMessage contains a `tool_call` whose `name` does not match any tool passed into the ToolNode constructor — typically because the tool was never attached to the Agent, was renamed, or the model hallucinated a name.","commonSituations":"Tools were added/removed on the Agent after a conversation started (the cached AIMessage references an old name); the model hallucinated a tool name; tool display name differs from internal `name`; a tool was renamed between flow versions and an old session replays.","solutions":["Attach the missing tool to the Agent node so it is registered in the ToolNode's tools array.","Use stable, immutable tool `name` values — avoid renaming tools after deployment.","Start a new chat session after changing the toolset so stale tool_calls do not replay.","Verify `tool.name` matches what the model is instructed to call."],"exampleFix":null,"handlingStrategy":"validation","validationCode":"function assertAllToolCallsResolvable(toolCalls, tools) {\n  const names = new Set(tools.map((t) => t.name))\n  for (const call of toolCalls ?? []) {\n    if (!names.has(call.name)) {\n      throw new Error(`Tool '${call.name}' is not attached. Available: ${[...names].join(', ')}`)\n    }\n  }\n}\n\nassertAllToolCallsResolvable(aiMessage.tool_calls, nodeTools)","typeGuard":"function toolIsRegistered(name: string, tools: { name: string }[]): boolean {\n  return tools.some((t) => t.name === name)\n}","tryCatchPattern":"try {\n  await toolNode.invoke(input, config)\n} catch (e) {\n  if (e?.message?.startsWith('Tool ') && e.message.endsWith(' not found.')) {\n    // model hallucinated or toolset changed — re-ask the agent without the stale call\n    return [{ content: `Tool not available: ${e.message}`, tool_call_id: call.id }]\n  }\n  throw e\n}","preventionTips":["Use stable, immutable tool `name` values; never rename a tool after deployment.","Start a new chat session after changing the Agent's toolset so stale tool_calls do not replay.","Attach every tool the model is instructed it may call."],"tags":["tools","tool-calling","runtime","agent"],"backgroundTag":null,"analyzedSha":"abe4a8601a058047b350c260676826e21dd14101","analyzedAt":"2026-08-12T16:04:40.823Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}