{"record":{"id":"430ca3a92957dabf","repo":"FlowiseAI/Flowise","slug":"geterrormessage-e","errorCode":null,"errorMessage":"${getErrorMessage(e)}","messagePattern":"\\$\\{getErrorMessage\\(e\\)\\}","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/components/nodes/agentflow/Agent/Agent.ts","lineNumber":2361,"sourceCode":"                    const errMsg = getErrorMessage(e)\n                    let toolInput = toolCall.args\n                    if (typeof errMsg === 'string' && errMsg.includes(TOOL_ARGS_PREFIX)) {\n                        const [_, args] = errMsg.split(TOOL_ARGS_PREFIX)\n                        try {\n                            toolInput = JSON.parse(args)\n                        } catch (e) {\n                            console.error('Error parsing tool input from tool:', e)\n                        }\n                    }\n\n                    usedTools.push({\n                        tool: selectedTool.name,\n                        toolInput,\n                        toolOutput: '',\n                        error: getErrorMessage(e)\n                    })\n                    sseStreamer?.streamUsedToolsEvent(chatId, flatten(usedTools))\n                    throw new Error(getErrorMessage(e))\n                }\n            }\n        }\n\n        // Return direct tool output if there's exactly one tool with returnDirect\n        if (response.tool_calls.length === 1) {\n            const selectedTool = toolsInstance.find((tool) => tool.name === response.tool_calls?.[0]?.name)\n            if (selectedTool && selectedTool.returnDirect) {\n                const lastToolOutput = usedTools[0]?.toolOutput || ''\n                const lastToolOutputString = typeof lastToolOutput === 'string' ? lastToolOutput : JSON.stringify(lastToolOutput, null, 2)\n\n                if (sseStreamer && !isStructuredOutput) {\n                    sseStreamer.streamTokenEvent(chatId, lastToolOutputString)\n                }\n\n                return {\n                    response: new AIMessageChunk(lastToolOutputString),\n                    usedTools,","sourceCodeStart":2343,"sourceCodeEnd":2379,"githubUrl":"https://github.com/FlowiseAI/Flowise/blob/abe4a8601a058047b350c260676826e21dd14101/packages/components/nodes/agentflow/Agent/Agent.ts#L2343-L2379","documentation":"Inside Agent.handleToolCalls, each tool invocation is wrapped in try/catch. On failure the error is logged, recorded into usedTools with the error message, streamed via sseStreamer, and re-thrown verbatim through getErrorMessage(e). This propagates the original tool failure (not wrapped) up to Agent.run's catch, which wraps it as 'Error in Agent node'.","triggerScenarios":"A configured tool node throwing during .invoke/.call: HTTP tool hitting a bad endpoint, calculator tool bad input, RAG/tool credential missing, custom tool code throwing, MCP tool transport error, tool input args failing JSON parse inside the tool.","commonSituations":"Tool sub-node missing its credential; tool API endpoint down or returning non-200; tool input schema mismatch; version skew between tool schema and tool implementation; network/firewall blocking the tool's outbound call.","solutions":["Identify which tool failed from the streamed usedTools event (selectedTool.name) and its error field.","Open that tool node and test it in isolation; fix its config/credential/endpoint.","If the tool is external, verify connectivity and auth from the Flowise host.","Re-run the agent once the failing tool is corrected; consider marking the tool optional if appropriate."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"async function safeToolInvoke(tool, input) {\n  try { return { ok: true, value: await tool.invoke(input) } }\n  catch (e) { return { ok: false, error: e } }\n}\n// pre-flight: validate tool is init'd and credentialed\nfor (const t of toolsInstance) {\n  if (typeof t.invoke !== 'function') throw new Error(`Tool ${t.name} is not invokable`)\n}","typeGuard":"function isInvokableTool(t) { return !!t && typeof t.invoke === 'function' }","tryCatchPattern":"try { /* agent.run */ }\ncatch (e) {\n  const m = e instanceof Error ? e.message : String(e)\n  // the streamed usedTools event carries the failing tool name + error;\n  // match on tool name to route to the right remediation\n  if (/401|Unauthorized/.test(m)) { /* refresh tool credential */ }\n  throw e\n}","preventionTips":["Configure credentials on every tool sub-node and test them in isolation.","Make tool endpoints resilient and retryable.","Monitor usedTools events for non-empty error fields."],"tags":["agent","tool-execution","propagation","tools"],"backgroundTag":null,"analyzedSha":"abe4a8601a058047b350c260676826e21dd14101","analyzedAt":"2026-08-12T16:04:40.823Z","schemaVersion":2},"datasetVersion":"2026-08-12T18:17:37.767Z"}