n8n-io/n8n · error · Error

SplitInBatches node input connections are managed by SplitIn

Error message

SplitInBatches node input connections are managed by SplitInBatchesBuilder

What it means

Thrown by SplitInBatchesNodeInstance.input(). SplitInBatches is a loop node whose input wiring must be set up through SplitInBatchesBuilder, which owns the loop-back connection. Calling .input() directly on the node would bypass that ownership and produce invalid loop wiring, so every connection entry point on the raw node throws.

Source

Thrown at packages/@n8n/workflow-sdk/src/workflow-builder/control-flow-builders/split-in-batches.ts:56

			...config,
			parameters: config.parameters,
		};
	}

	update(
		config: Partial<NodeConfig>,
	): NodeInstance<'n8n-nodes-base.splitInBatches', string, unknown> {
		return new SplitInBatchesNodeInstance({
			version: this.version,
			config: {
				...this.config,
				...config,
			},
		});
	}

	input(_index: number): InputTarget {
		throw new Error('SplitInBatches node input connections are managed by SplitInBatchesBuilder');
	}

	output(_index: number): OutputSelector<'n8n-nodes-base.splitInBatches', string, unknown> {
		throw new Error('SplitInBatches node output connections are managed by SplitInBatchesBuilder');
	}

	to<T extends NodeInstance<string, string, unknown>>(
		_target: T | T[] | InputTarget,
		_outputIndex?: number,
	): NodeChain<NodeInstance<'n8n-nodes-base.splitInBatches', string, unknown>, T> {
		throw new Error('SplitInBatches node connections are managed by SplitInBatchesBuilder');
	}

	onError<T extends NodeInstance<string, string, unknown>>(_handler: T): this {
		throw new Error('SplitInBatches node error handling is managed by SplitInBatchesBuilder');
	}

	getConnections(): DeclaredConnection[] {

View on GitHub (pinned to 5ac6606e81)

Solutions

  1. Create the node via the splitInBatches() factory and configure input through the builder's branches (each/done).
  2. Do not call .input() on a SplitInBatches node; obtain the builder and let it manage wiring.
  3. Type-narrow (isSplitInBatchesType) before calling generic connection helpers.

Example fix

// before
const sib = splitInBatches('sib', {});
source.to(sib.sibNode.input(0));
// after
splitInBatches('sib', { each: processNode, done: endNode }); // builder wires the input
Defensive patterns

Strategy: type-guard

Validate before calling

import { isSplitInBatchesType } from '@n8n/workflow-sdk/constants/node-types';

function safeInput(node: NodeInstance): InputTarget {
  if (isSplitInBatchesType(node.type)) {
    throw new Error('Use the SplitInBatchesBuilder to wire this node, not .input()');
  }
  return node.input(0);
}

Type guard

function isConnectionManagedNode(node: NodeInstance): boolean {
  return node.type === 'n8n-nodes-base.splitInBatches';
}

Try / catch

try {
  return node.input(index);
} catch (e) {
  if (e instanceof Error && /managed by SplitInBatchesBuilder/.test(e.message)) {
    // route through the builder instead
  }
  throw e;
}

Prevention

When it happens

Trigger: Calling sibNode.input(0) directly; generic node-walking code that iterates an array of nodes and unconditionally calls .input()/.output() without special-casing SplitInBatches.

Common situations: Writing a generic layout or connection utility that assumes all NodeInstance objects expose the same connection API; holding a reference to the inner SIB node instead of the builder.

Related errors


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