{"record":{"id":"75a5585d26f1560c","repo":"n8n-io/n8n","slug":"edge-edge-from-edge-to-leaves-output-slot","errorCode":null,"errorMessage":"Edge ${edge.from} → ${edge.to} leaves output slot ${edge.outputIndex}; only output slot 0 is supported yet","messagePattern":"Edge (.+?) → (.+?) leaves output slot (.+?); only output slot 0 is supported yet","errorType":"exception","errorClass":"UnimplementedError","httpStatus":null,"severity":"error","filePath":"packages/@n8n/engine/src/graph/validate-executable-graph.ts","lineNumber":58,"sourceCode":"\t\tfor (const index of [edge.outputIndex, edge.inputIndex]) {\n\t\t\tif (!Number.isInteger(index) || index < 0) {\n\t\t\t\tthrow new GraphValidationError(\n\t\t\t\t\t`Edge ${edge.from} → ${edge.to} has slot index ${index}; slot indices are non-negative integers`,\n\t\t\t\t);\n\t\t\t}\n\t\t\tif (index > MAX_SLOT_INDEX) {\n\t\t\t\tthrow new GraphValidationError(\n\t\t\t\t\t`Edge ${edge.from} → ${edge.to} has slot index ${index}; slot indices above ${MAX_SLOT_INDEX} are not supported yet`,\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\t}\n\n\t// TODO(CAT-2874): multi-slot outputs arrive with branching; until then only\n\t// output slot 0 fires, and the runtime can assume single-slot outputs.\n\tfor (const edge of graph.edges) {\n\t\tif (edge.outputIndex !== 0) {\n\t\t\tthrow new UnimplementedError(\n\t\t\t\t`Edge ${edge.from} → ${edge.to} leaves output slot ${edge.outputIndex}; only output slot 0 is supported yet`,\n\t\t\t);\n\t\t}\n\t}\n\n\t// TODO(CAT-3982): same-slot convergence gets a defined meaning (concatenation);\n\t// until then it is rejected rather than given accidental semantics.\n\tconst seenInputSlots = new Set<string>();\n\tfor (const edge of graph.edges) {\n\t\tconst slot = `${edge.to}#${edge.inputIndex}`;\n\t\tif (seenInputSlots.has(slot)) {\n\t\t\tthrow new UnimplementedError(\n\t\t\t\t`Node ${edge.to} has more than one edge into input slot ${edge.inputIndex}; converging branches on one slot is not supported yet`,\n\t\t\t);\n\t\t}\n\t\tseenInputSlots.add(slot);\n\t}\n}","sourceCodeStart":40,"sourceCodeEnd":76,"githubUrl":"https://github.com/n8n-io/n8n/blob/5ac6606e81f67bb9534255570cd4e86fd8101eee/packages/@n8n/engine/src/graph/validate-executable-graph.ts#L40-L76","documentation":"Thrown by validateExecutableGraph() as an UnimplementedError when a graph edge has outputIndex !== 0. The engine (n8n Engine 2.0) only fires output slot 0 today; multi-slot output branching is tracked under TODO(CAT-2874) and intentionally rejected rather than given accidental semantics. At the HTTP layer (POST /workflow-executions) it surfaces as a 501 {error:'unimplemented', reason:...}. The graph is structurally valid but uses a feature the runtime cannot execute yet.","triggerScenarios":"POST /workflow-executions with a graph whose edges array contains an edge object with outputIndex set to 1 or higher (the Zod GraphEdgeSchema defaults outputIndex to 0, so this only fires when the caller explicitly sends a non-zero outputIndex). Typical source: a workflow converted from the v1 model where a node branches to multiple outputs (e.g. an IF/Switch node's true/false outputs wired to different downstream nodes).","commonSituations":"Migrating an existing n8n workflow that uses conditional/branching nodes (IF, Switch, Merge) into the new engine before branching support lands. Auto-generating a graph from a v1 workflow JSON and copying the output connection index verbatim. Testing the engine with a hand-crafted multi-output graph.","solutions":["Collapse the branching into a single output: set outputIndex to 0 (or omit it, since the schema defaults to 0) on every edge so only slot 0 is used.","If you genuinely need multi-output branching, track CAT-2874 and keep the workflow on the v1 execution engine until it ships.","Pre-validate the graph client-side by asserting every edge.outputIndex === 0 before POSTing.","Catch the 501 unimplemented response and fall back to the legacy execution path for that workflow."],"exampleFix":"// before — edge on output slot 1 (IF node 'true' branch)\nconst graph = {\n  nodes: [...],\n  edges: [{ from: 'ifNode', to: 'doA', outputIndex: 1, inputIndex: 0 }]\n};\n// after — collapse to single output slot 0 (omit, schema defaults to 0)\nconst graph = {\n  nodes: [...],\n  edges: [{ from: 'ifNode', to: 'doA', inputIndex: 0 }]\n};","handlingStrategy":"validation","validationCode":"function assertSingleOutputSlot(graph) {\n  const bad = graph.edges.filter(e => e.outputIndex !== undefined && e.outputIndex !== 0);\n  if (bad.length) {\n    throw new Error(`Unsupported multi-slot outputs: ${JSON.stringify(bad)}`);\n  }\n}","typeGuard":"function usesOnlySlotZero(graph) {\n  return graph.edges.every(e => e.outputIndex === undefined || e.outputIndex === 0);\n}","tryCatchPattern":"// At the HTTP client: detect the 501 envelope\nconst res = await fetch('/workflow-executions', { method: 'POST', body: JSON.stringify(payload) });\nif (res.status === 501) {\n  const body = await res.json();\n  if (body.error === 'unimplemented' && body.reason.includes('output slot')) {\n    // collapse to slot 0 and resubmit, or fall back to v1 engine\n  }\n}","preventionTips":["Default every edge's outputIndex to 0 and only override when branching ships (CAT-2874).","Run a local assertSingleOutputSlot(graph) check before POSTing.","When porting v1 workflows, flatten IF/Switch outputs to a single downstream edge."],"tags":["engine","graph-validation","unimplemented","branching"],"backgroundTag":null,"analyzedSha":"5ac6606e81f67bb9534255570cd4e86fd8101eee","analyzedAt":"2026-08-12T05:26:35.080Z","schemaVersion":2},"datasetVersion":"2026-08-13T04:17:16.726Z"}