n8n-io/n8n · error · ExpressionExtensionError

union(): expected array arg, e.g. .union([1, 2, 3, 4])

Error message

union(): expected array arg, e.g. .union([1, 2, 3, 4])

What it means

Thrown as ExpressionExtensionError by the .union() array extension when its argument is not an array. union() concatenates the base array with another array and removes duplicates; a non-array argument cannot be iterated for the concatenation step, so it is rejected.

Source

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

	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;
}

function union(value: unknown[], extraArgs: unknown[][]): unknown[] {
	const [others] = extraArgs;
	if (!Array.isArray(others)) {
		throw new ExpressionExtensionError('union(): expected array arg, e.g. .union([1, 2, 3, 4])');
	}
	const newArr: unknown[] = Array.from(value);
	for (const v of others) {
		if (newArr.findIndex((w) => isEqual(w, v)) === -1) {
			newArr.push(v);
		}
	}
	return unique(newArr, []);
}

function difference(value: unknown[], extraArgs: unknown[][]): unknown[] {
	const [others] = extraArgs;
	if (!Array.isArray(others)) {
		throw new ExpressionExtensionError(
			'difference(): expected array arg, e.g. .difference([1, 2, 3, 4])',
		);
	}
	const newArr: unknown[] = [];

View on GitHub (pinned to 5ac6606e81)

Solutions

  1. Pass an array: .union([1,2,3,4]).
  2. If the argument is dynamic, ensure it is an array before calling: Array.isArray(arg) ? .union(arg) : .union([arg]).
  3. Coerce single values into a one-element array when a union with a scalar is intended.
  4. Confirm the upstream expression yields an array.

Example fix

// before — scalar argument
{{ $json.tags.union($json.moreTags) }} // if moreTags is a string, throws
// after — ensure array argument
{{ $json.tags.union(Array.isArray($json.moreTags) ? $json.moreTags : [$json.moreTags]) }}
Defensive patterns

Strategy: type-guard

Validate before calling

function unionSafe(arr, others) {
  if (!Array.isArray(others)) throw new TypeError('union(): expected array arg');
  return [...new Set([...arr, ...others])];
}

Type guard

function isUnionArgValid(others) { return Array.isArray(others); }

Try / catch

try {
  result = arr.union(others);
} catch (e) {
  if (e.name === 'ExpressionExtensionError' && /union.*array/i.test(e.message)) {
    // ensure others is an array: arr.union(Array.isArray(others) ? others : [others])
  }
}

Prevention

When it happens

Trigger: Calling .union() with a non-array: .union(5), .union('abc'), .union({a:1}), or .union() where the harness passes undefined (undefined fails Array.isArray). The expected form is .union([1,2,3,4]).

Common situations: Passing a scalar or object instead of an array. A template variable resolving to a single value rather than a list. Forgetting the brackets around the argument.

Related errors


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