n8n-io/n8n · error · NodeNotFoundError
NODES_NOT_FOUND
NODES_NOT_FOUND
Error message
Node with ID "${nodeId}" not found in workflow What it means
Thrown by remove_connection when validateNodeExists returns null for sourceNodeId and/or targetNodeId. The error includes foundSource and foundTarget booleans so the caller can tell which side is missing. Code is NODES_NOT_FOUND (plural) to distinguish from the single-node NODE_NOT_FOUND factory.
Source
Thrown at packages/@n8n/ai-workflow-builder.ee/src/tools/remove-connection.tool.ts:107
const state = getWorkflowState();
const workflow = getCurrentWorkflow(state);
// Report progress
reportProgress(reporter, 'Finding nodes to disconnect...');
// Find source and target nodes
const sourceNode = validateNodeExists(validatedInput.sourceNodeId, workflow.nodes);
const targetNode = validateNodeExists(validatedInput.targetNodeId, workflow.nodes);
// Check if both nodes exist
if (!sourceNode || !targetNode) {
const missingNodeId = !sourceNode
? validatedInput.sourceNodeId
: validatedInput.targetNodeId;
const nodeError = new NodeNotFoundError(missingNodeId);
const error = {
message: nodeError.message,
code: 'NODES_NOT_FOUND',
details: {
sourceNodeId: validatedInput.sourceNodeId,
targetNodeId: validatedInput.targetNodeId,
foundSource: !!sourceNode,
foundTarget: !!targetNode,
},
};
reporter.error(error);
return createErrorResponse(config, error);
}
logger?.debug('\n=== Remove Connection Tool ===');
logger?.debug(
`Attempting to remove connection: ${sourceNode.name} -> ${targetNode.name} (${validatedInput.connectionType})`,
);
// Report progress
reportProgress(View on GitHub (pinned to 5ac6606e81)
Solutions
- Inspect details.foundSource and details.foundTarget to identify the missing side.
- Resolve current IDs via list_nodes.
- Re-issue remove_connection with valid IDs.
Defensive patterns
Strategy: validation
Validate before calling
import { validateNodeExists } from '@/tools/helpers/validation';
const src = validateNodeExists(input.sourceNodeId, workflow.nodes);
const tgt = validateNodeExists(input.targetNodeId, workflow.nodes);
if (!src || !tgt) { /* surface which side is missing, refresh IDs */ } Type guard
function isToolError(v: unknown): v is { message: string; code: string; details?: { foundSource?: boolean; foundTarget?: boolean } } {
return typeof v === 'object' && v !== null && 'code' in v && (v as any).code === 'NODES_NOT_FOUND';
} Try / catch
const res = await remove_connection.invoke(input);
if (isToolError(res) && res.code === 'NODES_NOT_FOUND') {
if (!res.details?.foundSource) { /* re-resolve source */ }
if (!res.details?.foundTarget) { /* re-resolve target */ }
} Prevention
- Re-resolve node IDs after any add/delete operation.
- Pass stable UUIDs, not names, to remove_connection.
- Track deleted node IDs in the agent state to avoid stale references.
When it happens
Trigger: remove_connection invoked with a sourceNodeId or targetNodeId that does not match any node.id in workflow.nodes.
Common situations: Node was deleted between connect and disconnect; stale UUID; wrong workflow; ID typo.
Related errors
AI-assisted analysis of n8n-io/n8n@5ac6606e81 (2026-08-12).
Data as JSON: /api/errors/018af4935a3d2698.
Report an issue: GitHub.