remotion-dev/remotion · error · TypeError

"${name}" must be a [number, number] tuple

Error message

"${name}" must be a [number, number] tuple

What it means

The zoomBlur effect validates its optional `center` parameter, which must be a two-element array of finite numbers representing UV coordinates. If `center` is provided but is not exactly a `[number, number]` tuple (e.g., has 3 elements, contains a string, includes NaN/Infinity, or is a non-array value), this TypeError is thrown before any WebGL work begins. The check runs during `validateParams` which is invoked by the effect framework when the effect is set up or applied.

Source

Thrown at packages/effects/src/zoom-blur/index.ts:83

};

const resolve = (params: ZoomBlurParams): ZoomBlurResolved => ({
	amount: params.amount ?? DEFAULT_AMOUNT,
	center: [...(params.center ?? DEFAULT_CENTER)] as ZoomBlurCenter,
	samples: params.samples ?? DEFAULT_SAMPLES,
});

const assertOptionalUvCoordinate = (value: unknown, name: string): void => {
	if (value === undefined) {
		return;
	}

	if (
		!Array.isArray(value) ||
		value.length !== 2 ||
		value.some((item) => typeof item !== 'number' || !Number.isFinite(item))
	) {
		throw new TypeError(`"${name}" must be a [number, number] tuple`);
	}
};

const assertOptionalInteger = (value: unknown, name: string): void => {
	if (value === undefined) {
		return;
	}

	if (!Number.isInteger(value)) {
		throw new TypeError(
			`"${name}" must be an integer, but got ${JSON.stringify(value)}`,
		);
	}
};

const validateZoomBlurParams = (params: ZoomBlurParams): void => {
	assertEffectParamsObject(params, 'Zoom Blur');
	assertOptionalFiniteNumber(params.amount, 'amount');

View on GitHub (pinned to 78fe4bb3fd)

Solutions

  1. Ensure `center` is a flat two-element array of finite numbers, e.g. `center: [0.5, 0.5]`.
  2. If omitting `center`, remove the key entirely so the default `[0.5, 0.5]` applies.
  3. If your source data uses objects, map to an array before passing: `center: [data.x, data.y]`.

Example fix

// before
zoomBlur({ center: { x: 0.5, y: 0.5 } });

// after
zoomBlur({ center: [0.5, 0.5] });
Defensive patterns

Strategy: type-guard

Validate before calling

const isNumberTuple = (v: unknown): v is [number, number] =>
  Array.isArray(v) && v.length === 2 && v.every((n) => typeof n === 'number' && Number.isFinite(n));

if (center !== undefined && !isNumberTuple(center)) {
  // use default or throw a custom error
}

Type guard

const isUvCoordinate = (v: unknown): v is readonly [number, number] =>
  Array.isArray(v) &&
  v.length === 2 &&
  typeof v[0] === 'number' && Number.isFinite(v[0]) &&
  typeof v[1] === 'number' && Number.isFinite(v[1]);

Prevention

When it happens

Trigger: Passing `center` as `[[0.5, 0.5]]` (nested array), `[0.5]` (single element), `[0.5, 0.5, 0.5]` (three elements), `['0.5', '0.5']` (strings), `[NaN, 0.5]`, `[Infinity, 0.5]`, or a plain object `{x: 0.5, y: 0.5}` to `zoomBlur({center: ...})`.

Common situations: Deserialization from JSON that produces different array shapes, UI slider components emitting objects instead of arrays, spreading a nested structure accidentally, or passing pixel coordinates instead of normalized 0–1 UV coordinates.

Related errors


AI-assisted analysis of remotion-dev/remotion@78fe4bb3fd (2026-08-12). Data as JSON: /api/errors/2e2c0f3d139ed194. Report an issue: GitHub.