remotion-dev/remotion · error · TypeError

"${name}" must be >= 0, but got ${JSON.stringify(value)}

Error message

"${name}" must be >= 0, but got ${JSON.stringify(value)}

What it means

Thrown by validateUnitInterval in color-utils.ts when a value resolved to the [0,1] range is below 0. The dynamic name in the message identifies the offending field. For color-correction this covers 'pivot'; for color-key it covers 'similarity', 'smoothness', and 'spillSuppression'. It is a caller-input TypeError.

Source

Thrown at packages/effects/src/color-utils.ts:57

	step: 1,
	default: DEFAULT_HUE_DEGREES,
	description: 'Degrees',
} as const satisfies InteractivitySchema['degrees'];

export const assertOptionalFiniteNumber = (
	value: unknown,
	name: string,
): void => {
	if (value === undefined) {
		return;
	}

	assertRequiredFiniteNumber(value, name);
};

export const validateUnitInterval = (value: number, name: string): void => {
	if (value < 0) {
		throw new TypeError(
			`"${name}" must be >= 0, but got ${JSON.stringify(value)}`,
		);
	}

	if (value > 1) {
		throw new TypeError(
			`"${name}" must be <= 1, but got ${JSON.stringify(value)}`,
		);
	}
};

export const validateNonNegative = (value: number, name: string): void => {
	if (value < 0) {
		throw new TypeError(
			`"${name}" must be >= 0, but got ${JSON.stringify(value)}`,
		);
	}
};

View on GitHub (pinned to 78fe4bb3fd)

Solutions

  1. Clamp the value to [0,1] before passing it: Math.max(0, Math.min(1, value)).
  2. Use interpolate(..., {extrapolateLeft: 'clamp', extrapolateRight: 'clamp'}) so animation cannot leave the range.
  3. Inspect the field name and value in the error and fix the producer of that number.
  4. Omit the field to accept its documented default (e.g. similarity 0.18, smoothness 0.08, spillSuppression 0.25, pivot 0.5).

Example fix

// before
colorKey({similarity: -0.2}); // throws: similarity must be >= 0

// after
const similarity = Math.max(0, Math.min(1, animated));
colorKey({similarity});
Defensive patterns

Strategy: validation

Validate before calling

function assertUnitInterval(value: number | undefined, name: string): number | undefined {
  if (value === undefined) return value;
  if (!Number.isFinite(value)) {
    throw new TypeError(`${name} must be finite, got ${value}`);
  }
  if (value < 0 || value > 1) {
    throw new TypeError(`${name} must be in [0, 1], got ${value}`);
  }
  return value;
}

// colorCorrection({pivot: assertUnitInterval(pivot, 'pivot')})
// colorKey({
//   similarity: assertUnitInterval(sim, 'similarity'),
//   smoothness: assertUnitInterval(smooth, 'smoothness'),
//   spillSuppression: assertUnitInterval(spill, 'spillSuppression'),
// })

Type guard

const isUnitInterval = (v: unknown): v is number =>
  typeof v === 'number' && Number.isFinite(v) && v >= 0 && v <= 1;

Prevention

When it happens

Trigger: Reached when colorCorrection({pivot}) gets pivot < 0, or when colorKey({similarity | smoothness | spillSuppression}) gets a value < 0. Validation runs in validateColorCorrectionParams (color-correction.ts:181) or validateColorKeyParams (color-key.ts:107-109) via validateUnitInterval at color-utils.ts:56, before any GL work.

Common situations: Animated values from interpolate/Spring that undershoot below 0 without clamping, a value copied from another tool's scale, or a slider whose min was set below 0.

Related errors


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