n8n-io/n8n · error · ExpressionExtensionError

isEven() is only callable on integers

Error message

isEven() is only callable on integers

What it means

`isEven(value)` requires `Number.isInteger(value)` to be true. Non-integer numbers (3.5, NaN, Infinity) and non-number values throw before the modulo is computed.

Source

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

// The original uses Intl.NumberFormat which is a Web API unavailable inside the
// V8 isolate. toLocaleString is an ECMAScript built-in available in all V8
// contexts and produces the same output.
function format(value: number, extraArgs: unknown[]): string {
	const [locales = 'en-US', config = {}] = extraArgs as [
		string | string[],
		Intl.NumberFormatOptions,
	];

	try {
		return value.toLocaleString(locales as string, config);
	} catch {
		return String(value);
	}
}

function isEven(value: number) {
	if (!Number.isInteger(value)) {
		throw new ExpressionExtensionError('isEven() is only callable on integers');
	}
	return value % 2 === 0;
}

function isOdd(value: number) {
	if (!Number.isInteger(value)) {
		throw new ExpressionExtensionError('isOdd() is only callable on integers');
	}
	return Math.abs(value) % 2 === 1;
}

function floor(value: number) {
	return Math.floor(value);
}

function ceil(value: number) {
	return Math.ceil(value);
}

View on GitHub (pinned to 5ac6606e81)

Solutions

  1. Round first: `.floor().isEven()` or `.toInt().isEven()`.
  2. Validate the value is integral (`Number.isInteger(x)`) in a Code node before relying on the expression.
  3. If fractional parity is meaningless for your domain, filter those rows out upstream.

Example fix

// before
{{ $json.ratio.isEven() }}
// after
{{ $json.ratio.floor().isEven() }}
Defensive patterns

Strategy: type-guard

Validate before calling

if (!Number.isInteger($json.n)) {
  throw new Error('isEven(): value must be an integer, got ' + $json.n);
}
return $json;

Type guard

const isInteger = (v: unknown): v is number => typeof v === 'number' && Number.isInteger(v);

Prevention

When it happens

Trigger: `.isEven()` on `3.5`, on `NaN`, on a value that arrived as a float after division, or on a non-number that slipped past the type dispatch.

Common situations: Division or average result that is fractional; a parsed float where an integer was expected; currency amount with decimals.

Related errors


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