n8n-io/n8n · error · Error

Subnode connections are managed by parent node SubnodeConfig

Error message

Subnode connections are managed by parent node SubnodeConfig

What it means

Thrown by SubnodeInstanceImpl.then() — the fluent .then(target) chaining method is disabled for subnodes because their connection graph is controlled by the parent SubnodeConfig. Calling .then() on a subnode attempts to create a connection that the parent must own, so it is rejected at runtime.

Solutions

  1. Move the .then(...) call to the parent SubnodeConfig node.
  2. Skip subnodes in any generic chaining utility via a SubnodeInstanceImpl type guard.
  3. Use .to() on the parent for successor wiring instead of chaining off the subnode.

Example fix

// before
toolNode.then(downstream); // throws
// after
agent.then(downstream); // parent SubnodeConfig owns it
Defensive patterns

Strategy: type-guard

Validate before calling

if (!(node instanceof SubnodeInstanceImpl)) {
  node.then(target);
}

Type guard

function isSubnodeInstance(n: unknown): n is SubnodeInstanceImpl {
  return n instanceof SubnodeInstanceImpl;
}

Prevention

When it happens

Trigger: Writing toolNode.then(otherNode) as if the tool were a standalone node; using a generic pipeline helper that chains all nodes via .then().

Common situations: Porting a linear chain pattern to a graph that includes AI tools; auto-generating builder code that calls .then() uniformly.

Related errors


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

Appendix: source

Thrown at packages/@n8n/workflow-sdk/src/workflow-builder/node-builders/subnode-builders.ts:142

			this._subnodeType,
			this.id,
			this.name,
		);
	}

	input(_index: number): InputTarget {
		throw new Error('Subnode input connections are managed by parent node SubnodeConfig');
	}

	output(_index: number): OutputSelector<TType, TVersion, TOutput> {
		throw new Error('Subnode output connections are managed by parent node SubnodeConfig');
	}

	then<T extends NodeInstance<string, string, unknown>>(
		_target: T | T[] | InputTarget,
		_outputIndex?: number,
	): NodeChain<NodeInstance<TType, TVersion, TOutput>, T> {
		throw new Error('Subnode connections are managed by parent node SubnodeConfig');
	}

	to<T extends NodeInstance<string, string, unknown>>(
		_target: T | T[] | InputTarget,
		_outputIndex?: number,
	): NodeChain<NodeInstance<TType, TVersion, TOutput>, T> {
		throw new Error('Subnode connections are managed by parent node SubnodeConfig');
	}

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

	getConnections(): DeclaredConnection[] {
		return [];
	}
}

View on GitHub (pinned to 5ac6606e81)