n8n-io/n8n · error · Error
Named object syntax does not support .onDone() - branches ar
Error message
Named object syntax does not support .onDone() - branches are configured in the constructor
What it means
Thrown by NamedSplitInBatchesBuilderImpl.onDone(). Symmetric to onEachBatch: the named-object builder variant fixes the done branch in the constructor and does not accept the fluent .onDone() method, which would mutate the done target after construction.
Source
Thrown at packages/@n8n/workflow-sdk/src/workflow-builder/control-flow-builders/split-in-batches.ts:550
// expressed in the connection target (e.g., each: sibNode or each: processNode.to(sibNode))
// The workflow-builder's _hasLoop handling is only for the fluent API's .loop() method
}
}
/**
* Fluent API: Not supported for named syntax builder (use constructor branches instead)
*/
onEachBatch(_target: BranchTarget): this {
throw new Error(
'Named object syntax does not support .onEachBatch() - branches are configured in the constructor',
);
}
/**
* Fluent API: Not supported for named syntax builder (use constructor branches instead)
*/
onDone(_target: BranchTarget): this {
throw new Error(
'Named object syntax does not support .onDone() - branches are configured in the constructor',
);
}
getAllNodes(): Array<NodeInstance<string, string, unknown>> {
return [this.sibNode, ...this._doneNodes, ...this._eachNodes];
}
getDoneNodes(): Array<NodeInstance<string, string, unknown>> {
return this._doneNodes;
}
getEachNodes(): Array<NodeInstance<string, string, unknown>> {
return this._eachNodes;
}
hasLoop(): boolean {
return this._hasLoop;View on GitHub (pinned to 5ac6606e81)
Solutions
- Provide the done branch in the constructor object: splitInBatches('sib', { each, done: endNode }).
- Switch to the fluent builder variant if you need .onDone().
- Decide on one style (named vs fluent) per SplitInBatches and stay with it.
Example fix
// before
const sib = splitInBatches('sib', { each: processNode });
sib.onDone(endNode); // throws
// after
const sib = splitInBatches('sib', { each: processNode, done: endNode }); Defensive patterns
Strategy: type-guard
Validate before calling
function isNamedSyntaxBuilder(b: unknown): boolean {
return b instanceof NamedSplitInBatchesBuilderImpl;
}
if (isNamedSyntaxBuilder(builder)) {
throw new Error('Use constructor branches { each, done }, not .onDone()');
} Type guard
function supportsFluentBranches(b: SplitInBatchesBuilder): boolean {
return !Object.is(b.onDone, NamedSplitInBatchesBuilderImpl.prototype.onDone);
} Try / catch
try {
builder.onDone(target);
} catch (e) {
if (e instanceof Error && /Named object syntax does not support/.test(e.message)) {
// reconfigure via constructor branches instead
}
throw e;
} Prevention
- When using named syntax, supply `done` in the constructor object.
- Reserve .onDone() for the fluent builder variant.
- Do not mix named-object construction with fluent branch methods.
When it happens
Trigger: Constructing with named syntax and then calling .onDone(target) on the returned builder.
Common situations: Mixing styles; refactoring a fluent-style chain onto a named-syntax builder; appending a done handler after the fact.
Related errors
- Named object syntax does not support .onEachBatch() - branch
- SplitInBatches node input connections are managed by SplitIn
- SplitInBatches node output connections are managed by SplitI
- SplitInBatches node connections are managed by SplitInBatche
- SplitInBatches node error handling is managed by SplitInBatc
AI-assisted analysis of n8n-io/n8n@5ac6606e81 (2026-08-12).
Data as JSON: /api/errors/a41e64ae8cfc3780.
Report an issue: GitHub.