n8n-io/n8n · error · Error

Nodes from fromJSON() do not support onError()

Error message

Nodes from fromJSON() do not support onError()

What it means

Imported (fromJSON) node handles do not support onError(), which on authored nodes configures per-node error behavior (e.g. routing to an error output). Imported nodes read their error settings verbatim from the JSON's onError field, so the fluent mutator is disabled. The throw prevents silently losing error-handling config that the JSON already specifies.

Source

Thrown at packages/@n8n/workflow-sdk/src/workflow-builder/workflow-import.ts:103

				waitBetweenTries: n8nNode.waitBetweenTries,
				alwaysOutputData: n8nNode.alwaysOutputData,
				onError: n8nNode.onError,
				extendsCredential: n8nNode.extendsCredential,
			},
			update(config) {
				return { ...this, config: { ...this.config, ...config } };
			},
			to() {
				throw new Error('Nodes from fromJSON() do not support to()');
			},
			input() {
				throw new Error('Nodes from fromJSON() do not support input()');
			},
			output() {
				throw new Error('Nodes from fromJSON() do not support output()');
			},
			onError() {
				throw new Error('Nodes from fromJSON() do not support onError()');
			},
			getConnections() {
				return [];
			},
		};

		const connectionsMap = new Map<string, Map<number, ConnectionTarget[]>>();
		let mapKey = nodeName || `__unnamed_${unnamedCounter++}`;

		// Handle duplicate node names: generate unique key for duplicates
		// The first instance keeps the original name (connections reference it)
		if (nodes.has(mapKey)) {
			mapKey = generateUniqueName(nodeName, (n) => nodes.has(n));
		} else {
			nameToKey.set(nodeName, mapKey);
		}

		nodes.set(mapKey, {

View on GitHub (pinned to 5ac6606e81)

Solutions

  1. Set the onError field in the source JSON before importing.
  2. Re-author the node with the builder factory and use its .onError() API.
  3. Use node.update({ onError: ... }) which is supported on imported handles (it returns a new config without touching connections).

Example fix

// before
const n = wf.getNode('X'); // imported
n.onError(...); // throws

// after (option A: edit JSON)
json.nodes.find(x => x.name === 'X').onError = 'stopOnError';
workflow.fromJSON(json);

// after (option B: update config)
const updated = n.update({ onError: 'stopOnError' });
Defensive patterns

Strategy: validation

Validate before calling

function isImportedNode(n: any): boolean {
  return n.__imported === true;
}
if (isImportedNode(n)) {
  // use update() which is supported, instead of onError()
  return n.update({ onError: 'stopOnError' });
}

Type guard

function isImportedNode(n: { __imported?: boolean }): boolean {
  return n.__imported === true;
}

Try / catch

try {
  n.onError('stopOnError');
} catch (e) {
  if (e instanceof Error && e.message.includes('fromJSON()')) {
    return n.update({ onError: 'stopOnError' });
  }
  throw e;
}

Prevention

When it happens

Trigger: Calling node.onError(...) on a handle from fromJSON() to change its error routing after import.

Common situations: Post-import normalization that tries to standardize error handling; helper code that sets onError uniformly on all nodes.

Related errors


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