n8n-io/n8n · error · ExpressionExtensionError

keys and values must be arrays

Error message

keys and values must be arrays

What it means

The `zip(keys, values)` function-extensions helper builds an object from two parallel arrays. It throws `ExpressionExtensionError` when either argument fails `Array.isArray(...)`, because the subsequent loop indexes into them positionally.

Source

Thrown at packages/@n8n/expression-runtime/src/extensions/function-extensions.ts:25

const numberList = (start: number, end: number): number[] => {
	const size = Math.abs(start - end) + 1;
	const arr = new Array<number>(size);

	let curr = start;
	for (let i = 0; i < size; i++) {
		if (start < end) {
			arr[i] = curr++;
		} else {
			arr[i] = curr--;
		}
	}

	return arr;
};

const zip = (keys: unknown[], values: unknown[]): unknown => {
	if (!Array.isArray(keys) || !Array.isArray(values)) {
		throw new ExpressionExtensionError('keys and values must be arrays');
	}
	if (keys.length !== values.length) {
		throw new ExpressionExtensionError('keys and values not of equal length');
	}
	const result: Record<string, unknown> = {};
	for (let i = 0; i < keys.length; i++) {
		result[keys[i] as string] = values[i];
	}
	return result;
};

const average = (...args: number[]) => {
	return aAverage(args);
};

const not = (value: unknown): boolean => {
	return !value;
};

View on GitHub (pinned to 5ac6606e81)

Solutions

  1. Ensure both arguments are arrays — wrap with `[...]` or `Array.from(...)` in a Code node if needed.
  2. If the source is a delimited string, `.split(',')` it first.
  3. Confirm both upstream fields are typed as arrays before the expression runs.

Example fix

// before
{{ zip($json.headers, $json.rowObject) }}
// after
{{ zip($json.headers, $json.rowArray) }}
Defensive patterns

Strategy: validation

Validate before calling

const { keys, values } = $json;
if (!Array.isArray(keys) || !Array.isArray(values)) {
  throw new Error('zip(): keys and values must both be arrays');
}
return $json;

Type guard

const areBothArrays = (a: unknown, b: unknown): a is unknown[] & unknown[] =>
  Array.isArray(a) && Array.isArray(b);

Prevention

When it happens

Trigger: Passing a non-array argument: `{{ zip($json.headers, $json.row) }}` where `row` is an object or string; `{{ zip('a,b', [1,2]) }}`.

Common situations: Upstream field is a string or object instead of an array; passing a single value where a list was expected.

Related errors


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