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
- Ensure `center` is a flat two-element array of finite numbers, e.g. `center: [0.5, 0.5]`.
- If omitting `center`, remove the key entirely so the default `[0.5, 0.5]` applies.
- 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
- Always pass center as a literal two-element array of numbers.
- Validate deserialized data with a type guard before passing to zoomBlur.
- Use TypeScript's readonly tuple type to get compile-time checking.
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
- "${name}" must be an integer, but got ${JSON.stringify(value
- "${name}" must be greater than 0, but got ${JSON.stringify(v
- "${name}" must be greater than or equal to 0, but got ${JSON
- "colors" must be an array with at least 2 colors, but got ${
- "${name}" must be greater than 0, but got ${JSON.stringify(v
AI-assisted analysis of remotion-dev/remotion@78fe4bb3fd (2026-08-12).
Data as JSON: /api/errors/2e2c0f3d139ed194.
Report an issue: GitHub.