remotion-dev/remotion · error · TypeError

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

Error message

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

What it means

Thrown by assertOptionalUvCoordinate when radialProgressiveBlur is given a `center` value that is not undefined and not a 2-element array of finite numbers. The center is a UV coordinate pair, so the runtime strictly requires the [number, number] tuple shape before any GL work happens. A TypeError (not Error) is used because this is a caller-contract violation.

Source

Thrown at packages/effects/src/radial-progressive-blur/index.ts:163

	width: params.width ?? DEFAULT_WIDTH,
	height: params.height ?? DEFAULT_HEIGHT,
	rotation: params.rotation ?? DEFAULT_ROTATION,
	start: params.start ?? DEFAULT_START,
	startBlur: clampBlur(params.startBlur ?? DEFAULT_START_BLUR),
	endBlur: clampBlur(params.endBlur ?? DEFAULT_END_BLUR),
});

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 validateRadialProgressiveBlurParams = (
	params: RadialProgressiveBlurParams,
): void => {
	assertEffectParamsObject(params, 'Radial progressive blur');
	assertOptionalUvCoordinate(params.center, 'center');
	assertOptionalFiniteNumber(params.width, 'width');
	assertOptionalFiniteNumber(params.height, 'height');
	assertOptionalFiniteNumber(params.rotation, 'rotation');
	validateNonNegative(params.width ?? DEFAULT_WIDTH, 'width');
	validateNonNegative(params.height ?? DEFAULT_HEIGHT, 'height');
	assertOptionalFiniteNumber(params.start, 'start');
	validateUnitInterval(params.start ?? DEFAULT_START, 'start');
	assertOptionalFiniteNumber(params.startBlur, 'startBlur');
	assertOptionalFiniteNumber(params.endBlur, 'endBlur');
};

View on GitHub (pinned to 78fe4bb3fd)

Solutions

  1. Pass exactly two finite numbers: `radialProgressiveBlur({center: [0.5, 0.5]})`.
  2. When animating, build the tuple with an explicit expression: `center: [interpolate(...), interpolate(...)] as [number, number]`.
  3. If you do not need to set center, omit it entirely — it defaults to a valid value.
  4. Convert library vector objects to plain arrays before passing: `[vec.x, vec.y]`.
  5. Validate deserialized input with the type guard below before feeding it to the effect.

Example fix

// before
import {radialProgressiveBlur} from '@remotion/effects';
const e = radialProgressiveBlur({center: {x: 0.5, y: 0.5}}); // throws TypeError
// or
const e2 = radialProgressiveBlur({center: [0.5]}); // throws TypeError

// after
const e = radialProgressiveBlur({center: [0.5, 0.5]});
// or omit it:
const e3 = radialProgressiveBlur({});
Defensive patterns

Strategy: type-guard

Validate before calling

function asUvCoordinate(v: unknown): [number, number] | undefined {
  if (v === undefined) return undefined;
  if (
    Array.isArray(v) &&
    v.length === 2 &&
    v.every((n) => typeof n === 'number' && Number.isFinite(n))
  ) {
    return [v[0], v[1]];
  }
  throw new TypeError('"center" must be a [number, number] tuple');
}
const center = asUvCoordinate(maybeCenter);
const effect = radialProgressiveBlur(center === undefined ? {} : {center});

Type guard

function isUvCoordinate(v: unknown): v is [number, number] {
  return (
    Array.isArray(v) &&
    v.length === 2 &&
    v.every((n) => typeof n === 'number' && Number.isFinite(n))
  );
}

Prevention

When it happens

Trigger: Calling `radialProgressiveBlur({center: ...})` with a value that is: an array of length ≠ 2 (e.g. `[0.5]` or `[0.5, 0.5, 0.5]`); an array containing a non-number or non-finite element (e.g. `[0.5, NaN]`, `[0.5, '0.5']`, `[0.5, null]`); or a non-array truthy object (e.g. `{x: 0.5, y: 0.5}`).

Common situations: Passing a Vec2/Vector2 object from another library instead of a plain array; animating center with interpolate() but returning 3 or 1 components; copy-pasting a value from an effect that uses [x, y, z]; deserializing JSON where the tuple lost a component; passing `[0.5, undefined]`.

Related errors


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