remotion-dev/remotion · error · TypeError
"${name}" must be a [number, number] tuple
Error message
"${name}" must be a [number, number] tuple What it means
TypeError thrown by vignette's assertOptionalUvCoordinate when params.center is defined but is not exactly a 2-element array of finite numbers. The validator requires [number, number]; it rejects arrays of other lengths, non-arrays, and elements that are not finite numbers (NaN/Infinity included). center is optional, so undefined is accepted and defaults to [0.5, 0.5].
Source
Thrown at packages/effects/src/vignette.ts:184
radius: p.radius ?? DEFAULT_RADIUS,
feather: p.feather ?? DEFAULT_FEATHER,
roundness: p.roundness ?? DEFAULT_ROUNDNESS,
color: p.color ?? DEFAULT_COLOR,
mode: p.mode ?? DEFAULT_MODE,
center: [...(p.center ?? DEFAULT_CENTER)] as VignetteCenter,
});
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 validateVignetteParams = (params: VignetteParams): void => {
assertEffectParamsObject(params, 'Vignette');
assertOptionalFiniteNumber(params.amount, 'amount');
assertOptionalFiniteNumber(params.radius, 'radius');
assertOptionalFiniteNumber(params.feather, 'feather');
assertOptionalFiniteNumber(params.roundness, 'roundness');
assertOptionalColor(params.color, 'color');
assertOptionalEnum(params.mode, 'mode', VIGNETTE_MODES);
assertOptionalUvCoordinate(params.center, 'center');
const r = resolve(params);
validateUnitInterval(r.amount, 'amount');
validateUnitInterval(r.radius, 'radius');
validateUnitInterval(r.feather, 'feather');
validateUnitInterval(r.roundness, 'roundness');View on GitHub (pinned to 78fe4bb3fd)
Solutions
- Pass exactly a [number, number] tuple of finite values, e.g. center: [0.5, 0.5].
- If center is optional for your case, omit it to use the default.
- Sanitise dynamic input: coerce with Number() and guard Number.isFinite before building the tuple.
- Type the prop as readonly [number, number] so the compiler flags shape mistakes.
Example fix
// before
const e = vignette({center: {x: 0.5, y: 0.5}}); // throws TypeError
// after
const e = vignette({center: [0.5, 0.5]});
// or omit
const e2 = vignette({}); Defensive patterns
Strategy: type-guard
Validate before calling
const isFiniteTuple2 = (v: unknown): v is [number, number] =>
Array.isArray(v) &&
v.length === 2 &&
v.every((item) => typeof item === 'number' && Number.isFinite(item));
const center = isFiniteTuple2(config.center) ? config.center : undefined;
const e = vignette({center, amount: 0.6}); Type guard
const isUvCoordinate = (v: unknown): v is [number, number] => Array.isArray(v) && v.length === 2 && typeof v[0] === 'number' && typeof v[1] === 'number' && Number.isFinite(v[0]) && Number.isFinite(v[1]);
Try / catch
try {
const e = vignette({center: config.center, amount: 0.6});
} catch (err) {
if (err instanceof TypeError) {
console.error('Invalid vignette center:', config.center, err);
}
throw err;
} Prevention
- Type center as readonly [number, number] so shape errors surface at compile time.
- Sanitise external/dynamic input with a tuple guard before passing it.
- Coerce numeric strings with Number() and reject NaN/Infinity explicitly.
- Do not pass {x, y} objects; convert them to [x, y] tuples first.
When it happens
Trigger: vignette({center: [0.5]}) (length 1), vignette({center: [0.5, 0.5, 0.5]}) (length 3), vignette({center: 'center'}), vignette({center: {x: 0.5, y: 0.5}}), vignette({center: [0.5, NaN]}), or vignette({center: [0.5, '0.5']}).
Common situations: Passing an {x,y} object instead of a tuple; truncating or extending the array; serialised values where a number became a string; feeding mouse/pointer coordinates that yield NaN.
Related errors
- "${name}" must be ${formatEnum(variants)}, but got ${JSON.st
- "${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 ${
- "exposure" must be >= ${MIN_EXPOSURE}, but got ${JSON.string
AI-assisted analysis of remotion-dev/remotion@78fe4bb3fd (2026-08-12).
Data as JSON: /api/errors/3f2a3859fa060023.
Report an issue: GitHub.