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 skew() effect's assertOptionalUvCoordinate helper validates the optional 'origin' parameter. If provided, it must be an array of exactly two finite numbers — a [number, number] tuple in UV coordinate space. Passing anything else (wrong length, non-array, non-number elements, NaN/Infinity) throws this TypeError before the effect runs.
Source
Thrown at packages/effects/src/skew.ts:86
};
const resolve = (params: SkewParams): SkewResolved => ({
x: params.x ?? DEFAULT_X,
y: params.y ?? DEFAULT_Y,
origin: [...(params.origin ?? DEFAULT_ORIGIN)] as SkewOrigin,
});
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 validateUvCoordinate = (value: number, name: string): void => {
if (value < 0 || value > 1) {
throw new TypeError(
`"${name}" must be between 0 and 1, but got ${JSON.stringify(value)}`,
);
}
};
const validateAngle = (value: number, name: string): void => {
if (Math.abs(value) >= MAX_ABSOLUTE_ANGLE) {
throw new TypeError(
`"${name}" must be greater than -${MAX_ABSOLUTE_ANGLE} and less than ${MAX_ABSOLUTE_ANGLE}, but got ${JSON.stringify(value)}`,
);
}
};View on GitHub (pinned to 78fe4bb3fd)
Solutions
- Ensure origin is a 2-element array of finite numbers: [x, y] where both are numbers (not strings, not NaN, not null).
- Omit origin entirely to use the default [0.5, 0.5].
- If the value comes from user input or deserialization, validate it before passing to skew().
- Use a TypeScript type annotation (SkewOrigin = readonly [number, number]) to catch mismatches at compile time.
Example fix
// before — wrong shape
skew({ x: 20, y: 10, origin: { x: 0.5, y: 0.5 } })
// before — wrong length
skew({ x: 20, y: 10, origin: [0.5, 0.5, 0] })
// after — correct [number, number] tuple
skew({ x: 20, y: 10, origin: [0.5, 0.5] }) Defensive patterns
Strategy: type-guard
Validate before calling
// Validate the origin tuple before calling skew
function validateSkewOrigin(origin: unknown): [number, number] {
if (origin === undefined) return [0.5, 0.5]; // default
if (
Array.isArray(origin) &&
origin.length === 2 &&
origin.every((v) => typeof v === 'number' && Number.isFinite(v))
) {
return [origin[0], origin[1]];
}
throw new Error('origin must be a [number, number] tuple of finite values');
}
const origin = validateSkewOrigin(userInput);
skew({ x: 20, y: 0, origin }); Type guard
const isNumberTuple = (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]);
// Usage:
if (isNumberTuple(params.origin)) {
skew({ x: 20, origin: params.origin });
} else {
// handle invalid shape
} Try / catch
try {
skew({ x: 20, y: 0, origin: rawOrigin });
} catch (e) {
if (e instanceof TypeError && e.message.includes('[number, number] tuple')) {
// Fall back to default origin
skew({ x: 20, y: 0 });
} else {
throw e;
}
} Prevention
- Always pass origin as a 2-element array of finite numbers: [x, y].
- Omit origin entirely to use the default [0.5, 0.5].
- Use the SkewOrigin type (readonly [number, number]) to catch mismatches at compile time.
- Validate deserialized or user-provided origin values before passing them to skew().
When it happens
Trigger: Calling skew({ origin: [0.5] }) (wrong length), skew({ origin: 'center' }) (not an array), skew({ origin: [0.5, 0.5, 0.5] }) (three elements), skew({ origin: [0.5, NaN] }) (non-finite element), or skew({ origin: [0.5, '0.5'] }) (string element). The parameter is optional — omitting it entirely is valid and uses the default [0.5, 0.5].
Common situations: Passing a 3-element vector or object {x, y} instead of a 2-element array; deserializing origin from JSON that used a different format; spreading an array of unknown length; passing a React state variable that was initialized to null or an empty array.
Related errors
- "${name}" must be between 0 and 1, but got ${JSON.stringify(
- "${name}" must be greater than -${MAX_ABSOLUTE_ANGLE} and le
- "${name}" must be a [number, number] tuple
- "${name}" must be a [number, number] tuple
- "${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/6f7b4ae31ad0da91.
Report an issue: GitHub.