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

  1. Ensure origin is a 2-element array of finite numbers: [x, y] where both are numbers (not strings, not NaN, not null).
  2. Omit origin entirely to use the default [0.5, 0.5].
  3. If the value comes from user input or deserialization, validate it before passing to skew().
  4. 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

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


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