n8n-io/n8n · error · ExpressionExtensionError

chunk(): expected non-zero numeric arg, e.g. .chunk(5)

Error message

chunk(): expected non-zero numeric arg, e.g. .chunk(5)

What it means

Thrown as ExpressionExtensionError by the .chunk() array extension when chunkSize is not a number or is exactly zero. chunk() splits the array into sub-arrays of length chunkSize; a zero or non-numeric size is invalid (zero would also cause an infinite loop in the for-loop, so it is rejected up front).

Source

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

		throw new ExpressionExtensionError(
			'smartJoin(): expected two string args, e.g. .smartJoin("name", "value")',
		);
	}
	// eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/no-unsafe-return
	return value.reduce<any>((o, v) => {
		if (typeof v === 'object' && v !== null && keyField in v && valueField in v) {
			// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-explicit-any
			o[(v as any)[keyField]] = (v as any)[valueField];
		}
		// eslint-disable-next-line @typescript-eslint/no-unsafe-return
		return o;
	}, {});
}

function chunk(value: unknown[], extraArgs: number[]) {
	const [chunkSize] = extraArgs;
	if (typeof chunkSize !== 'number' || chunkSize === 0) {
		throw new ExpressionExtensionError('chunk(): expected non-zero numeric arg, e.g. .chunk(5)');
	}
	const chunks: unknown[][] = [];
	for (let i = 0; i < value.length; i += chunkSize) {
		chunks.push(value.slice(i, i + chunkSize));
	}
	return chunks;
}

function renameKeys(value: unknown[], extraArgs: string[]): unknown[] {
	if (extraArgs.length === 0 || extraArgs.length % 2 !== 0) {
		throw new ExpressionExtensionError(
			'renameKeys(): expected an even amount of args: from1, to1 [, from2, to2, ...]. e.g. .renameKeys("name", "title")',
		);
	}
	return value.map((v) => {
		if (typeof v !== 'object' || v === null) {
			return v;
		}

View on GitHub (pinned to 5ac6606e81)

Solutions

  1. Pass a positive integer: .chunk(5).
  2. If the size is dynamic, coerce and validate it first: .chunk(Number(size)).
  3. Guard against zero/undefined before calling: only call chunk when size is a positive number.
  4. Confirm the upstream expression that produces chunkSize yields a number.

Example fix

// before — chunk size from upstream data is a string or undefined
{{ $json.items.chunk($json.size) }}
// after — coerce to a positive integer
{{ $json.items.chunk(Number($json.size)) }}
Defensive patterns

Strategy: validation

Validate before calling

function chunkSafe(arr, size) {
  if (typeof size !== 'number' || size === 0) throw new TypeError('chunk(): expected non-zero numeric arg');
  const out = []; for (let i = 0; i < arr.length; i += size) out.push(arr.slice(i, i + size)); return out;
}

Type guard

function isValidChunkSize(size) { return typeof size === 'number' && size !== 0; }

Try / catch

try {
  result = arr.chunk(size);
} catch (e) {
  if (e.name === 'ExpressionExtensionError' && /chunk/i.test(e.message)) {
    // ensure size is a non-zero number: arr.chunk(Number(size) || 1)
  }
}

Prevention

When it happens

Trigger: Calling .chunk() with no argument, a string, or 0. Examples: [1,2,3].chunk() (missing), [1,2,3].chunk('2') (string), [1,2,3].chunk(0) (zero). Negative sizes would pass the type check but the loop degrades; the guard focuses on the dangerous zero/non-number cases.

Common situations: Passing a dynamic chunk size that resolved to undefined or a string from upstream data. Hardcoding 0 by mistake. A template variable for chunk size that wasn't converted to a number.

Related errors


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