n8n-io/n8n · error · UnimplementedError

Edge ${edge.from} → ${edge.to} leaves output slot ${edge.out

Error message

Edge ${edge.from} → ${edge.to} leaves output slot ${edge.outputIndex}; only output slot 0 is supported yet

What it means

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.

Source

Thrown at packages/@n8n/engine/src/graph/validate-executable-graph.ts:58

		for (const index of [edge.outputIndex, edge.inputIndex]) {
			if (!Number.isInteger(index) || index < 0) {
				throw new GraphValidationError(
					`Edge ${edge.from} → ${edge.to} has slot index ${index}; slot indices are non-negative integers`,
				);
			}
			if (index > MAX_SLOT_INDEX) {
				throw new GraphValidationError(
					`Edge ${edge.from} → ${edge.to} has slot index ${index}; slot indices above ${MAX_SLOT_INDEX} are not supported yet`,
				);
			}
		}
	}

	// TODO(CAT-2874): multi-slot outputs arrive with branching; until then only
	// output slot 0 fires, and the runtime can assume single-slot outputs.
	for (const edge of graph.edges) {
		if (edge.outputIndex !== 0) {
			throw new UnimplementedError(
				`Edge ${edge.from} → ${edge.to} leaves output slot ${edge.outputIndex}; only output slot 0 is supported yet`,
			);
		}
	}

	// TODO(CAT-3982): same-slot convergence gets a defined meaning (concatenation);
	// until then it is rejected rather than given accidental semantics.
	const seenInputSlots = new Set<string>();
	for (const edge of graph.edges) {
		const slot = `${edge.to}#${edge.inputIndex}`;
		if (seenInputSlots.has(slot)) {
			throw new UnimplementedError(
				`Node ${edge.to} has more than one edge into input slot ${edge.inputIndex}; converging branches on one slot is not supported yet`,
			);
		}
		seenInputSlots.add(slot);
	}
}

View on GitHub (pinned to 5ac6606e81)

Solutions

  1. 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.
  2. If you genuinely need multi-output branching, track CAT-2874 and keep the workflow on the v1 execution engine until it ships.
  3. Pre-validate the graph client-side by asserting every edge.outputIndex === 0 before POSTing.
  4. Catch the 501 unimplemented response and fall back to the legacy execution path for that workflow.

Example fix

// before — edge on output slot 1 (IF node 'true' branch)
const graph = {
  nodes: [...],
  edges: [{ from: 'ifNode', to: 'doA', outputIndex: 1, inputIndex: 0 }]
};
// after — collapse to single output slot 0 (omit, schema defaults to 0)
const graph = {
  nodes: [...],
  edges: [{ from: 'ifNode', to: 'doA', inputIndex: 0 }]
};
Defensive patterns

Strategy: validation

Validate before calling

function assertSingleOutputSlot(graph) {
  const bad = graph.edges.filter(e => e.outputIndex !== undefined && e.outputIndex !== 0);
  if (bad.length) {
    throw new Error(`Unsupported multi-slot outputs: ${JSON.stringify(bad)}`);
  }
}

Type guard

function usesOnlySlotZero(graph) {
  return graph.edges.every(e => e.outputIndex === undefined || e.outputIndex === 0);
}

Try / catch

// At the HTTP client: detect the 501 envelope
const res = await fetch('/workflow-executions', { method: 'POST', body: JSON.stringify(payload) });
if (res.status === 501) {
  const body = await res.json();
  if (body.error === 'unimplemented' && body.reason.includes('output slot')) {
    // collapse to slot 0 and resubmit, or fall back to v1 engine
  }
}

Prevention

When it happens

Trigger: 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).

Common situations: 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.

Related errors


AI-assisted analysis of n8n-io/n8n@5ac6606e81 (2026-08-12). Data as JSON: /api/errors/75a5585d26f1560c. Report an issue: GitHub.