n8n-io/n8n · error · ExpressionExtensionError

merge(): expected array arg, e.g. .merge([{ id: 1, otherValu

Error message

merge(): expected array arg, e.g. .merge([{ id: 1, otherValue: 3 }])

What it means

Thrown as ExpressionExtensionError by the .merge() array extension when its argument is present but not an array. merge() merges two object-arrays element-by-element; if called with no argument it instead merges all objects within the array itself. A present-but-non-array argument (e.g. a single object) is invalid because merge iterates by index against the base array.

Source

Thrown at packages/@n8n/expression-runtime/src/extensions/array-extensions.ts:250

	return newObject;
}

function merge(value: unknown[], extraArgs: unknown[][]): unknown {
	const [others] = extraArgs;

	if (others === undefined) {
		// If there are no arguments passed, merge all objects within the array
		const merged = value.reduce((combined, current) => {
			if (current !== null && typeof current === 'object' && !Array.isArray(current)) {
				combined = mergeObjects(combined as Record<string, unknown>, [current]);
			}
			return combined;
		}, {});
		return merged;
	}

	if (!Array.isArray(others)) {
		throw new ExpressionExtensionError(
			'merge(): expected array arg, e.g. .merge([{ id: 1, otherValue: 3 }])',
		);
	}
	const listLength = value.length > others.length ? value.length : others.length;
	let merged = {};
	for (let i = 0; i < listLength; i++) {
		if (value[i] !== undefined) {
			if (typeof value[i] === 'object' && typeof others[i] === 'object') {
				merged = Object.assign(
					merged,
					mergeObjects(value[i] as Record<string, unknown>, [others[i]]),
				);
			}
		}
	}
	return merged;
}

View on GitHub (pinned to 5ac6606e81)

Solutions

  1. Wrap the argument in an array: .merge([{id:1, otherValue:3}]).
  2. If you want to merge all objects within the array itself, call .merge() with NO argument.
  3. Guard with Array.isArray(arg) before calling.
  4. Match the documented shape exactly: base array + array argument.

Example fix

// before — single object argument
{{ $json.rows.merge({ id: 1, otherValue: 3 }) }}
// after — array argument
{{ $json.rows.merge([{ id: 1, otherValue: 3 }]) }}
Defensive patterns

Strategy: type-guard

Validate before calling

function mergeSafe(arr, others) {
  if (others !== undefined && !Array.isArray(others)) throw new TypeError('merge(): expected array arg');
  // ...proceed with arr.merge(others)
}

Type guard

function isMergeArgValid(others) { return others === undefined || Array.isArray(others); }

Try / catch

try {
  result = arr.merge(others);
} catch (e) {
  if (e.name === 'ExpressionExtensionError' && /merge.*array/i.test(e.message)) {
    // wrap the argument in an array: arr.merge([others])
  }
}

Prevention

When it happens

Trigger: Calling .merge() with a single object instead of an array of objects: [...].merge({id:1}) instead of [...].merge([{id:1}]). The check `if (!Array.isArray(others))` catches primitives, plain objects, strings, etc.

Common situations: Passing a bare object literal when the API expects an array of objects. A template variable that resolves to an object rather than an array. Misreading the doc example and dropping the enclosing brackets.

Related errors


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