remotion-dev/remotion · error · TypeError

"rotation" must be a finite number, but got ${JSON.stringify

Error message

"rotation" must be a finite number, but got ${JSON.stringify(params.rotation)}

What it means

validateStarburstEffectParams() throws this TypeError when rotation resolves to a non-finite value. rotation is optional with a default of 0 (see resolve()), so this only fires when the caller explicitly passes a non-number or non-finite number (NaN, Infinity) for rotation — the default never triggers it.

Source

Thrown at packages/effects/src/starburst.ts:118

		throw new TypeError(
			`"rays" must be a finite number, but got ${JSON.stringify(rays)}`,
		);
	}

	if (rays < 2 || rays > 100) {
		throw new RangeError(`"rays" must be between 2 and 100, but got ${rays}`);
	}

	if (!Array.isArray(colors) || colors.length < 2) {
		throw new TypeError(
			`"colors" must be an array with at least 2 colors, but got ${JSON.stringify(colors)}`,
		);
	}

	const r = resolve(params);

	if (typeof r.rotation !== 'number' || !Number.isFinite(r.rotation)) {
		throw new TypeError(
			`"rotation" must be a finite number, but got ${JSON.stringify(params.rotation)}`,
		);
	}

	if (typeof r.smoothness !== 'number' || !Number.isFinite(r.smoothness)) {
		throw new TypeError(
			`"smoothness" must be a finite number, but got ${JSON.stringify(params.smoothness)}`,
		);
	}

	if (r.smoothness < 0 || r.smoothness > 1) {
		throw new RangeError(
			`"smoothness" must be between 0 and 1, but got ${r.smoothness}`,
		);
	}

	if (
		!Array.isArray(r.origin) ||

View on GitHub (pinned to 78fe4bb3fd)

Solutions

  1. Pass a finite number for rotation, or omit it to use the default 0: starburst({ rays, colors }) or starburst({ rays, colors, rotation: 45 }).
  2. If rotation comes from user input, coerce and validate with Number() + Number.isFinite before calling starburst().
  3. Annotate the source variable as number in TypeScript so non-numbers are caught at compile time.
  4. Audit interpolation/animation code for NaN at edge frames.

Example fix

// before
starburst({ rays: 12, colors: ['#ff0000','#00ff00'], rotation: Number(inputAngle) }); // NaN if inputAngle is bad

// after
const rotation = Number(inputAngle);
starburst({
  rays: 12,
  colors: ['#ff0000','#00ff00'],
  rotation: Number.isFinite(rotation) ? rotation : 0,
});
Defensive patterns

Strategy: validation

Validate before calling

function resolveRotation(v: unknown): number {
  if (v === undefined) return 0;
  if (typeof v !== 'number' || !Number.isFinite(v)) {
    throw new TypeError(`"rotation" must be a finite number, but got ${JSON.stringify(v)}`);
  }
  return v;
}

starburst({ rays, colors, rotation: resolveRotation(input.rotation) });

Type guard

function isOptionalFiniteNumber(v: unknown): v is number | undefined {
  return v === undefined || (typeof v === 'number' && Number.isFinite(v));
}

Try / catch

try {
  starburst({ rays, colors, rotation });
} catch (err) {
  if (err instanceof TypeError && /"rotation" must be a finite number/.test(err.message)) {
    // rotation is optional — drop it and retry with the default of 0
    starburst({ rays, colors });
    return;
  }
  throw err;
}

Prevention

When it happens

Trigger: Calling starburst({ rays, colors, rotation: NaN }), rotation: Infinity, or rotation: '45' (string). Because resolve() applies `?? 0`, omitting rotation is safe; only an explicitly bad value reaches this check.

Common situations: Feeding rotation from arithmetic that can yield NaN (e.g. parsing a malformed angle string with Number()); passing a string from a UI field without coercion; copying a value from a different unit/field; animation interpolation that produced NaN at a boundary.

Related errors


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