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

TypeError thrown by halftone-linear-gradient's validateNonNegative (halftone-linear-gradient.ts:194) when a value allowed to be zero is negative. It guards firstStopDotSize and secondStopDotSize (the dot radius at each gradient stop). Zero dots are valid (no dot), negatives are not.

Source

Thrown at packages/effects/src/halftone-linear-gradient.ts:196

): HalftoneLinearGradientResolved => ({
	firstStopDotSize: p.firstStopDotSize ?? DEFAULT_FIRST_STOP_DOT_SIZE,
	secondStopDotSize: p.secondStopDotSize ?? DEFAULT_SECOND_STOP_DOT_SIZE,
	firstStopPosition: [
		...(p.firstStopPosition ?? DEFAULT_FIRST_STOP_POSITION),
	] as UvCoordinate,
	secondStopPosition: [
		...(p.secondStopPosition ?? DEFAULT_SECOND_STOP_POSITION),
	] as UvCoordinate,
	gridSize: p.gridSize ?? DEFAULT_GRID_SIZE,
	colorMode: p.colorMode ?? 'solid',
	dotColor:
		'dotColor' in p ? (p.dotColor ?? DEFAULT_DOT_COLOR) : DEFAULT_DOT_COLOR,
	maskToSourceAlpha: p.maskToSourceAlpha ?? DEFAULT_MASK_TO_SOURCE_ALPHA,
});

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

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

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

View on GitHub (pinned to 78fe4bb3fd)

Solutions

  1. Pass dot sizes as 0 or positive numbers.
  2. Clamp animated values: Math.max(0, value).
  3. If you meant 'no dots at this stop', use 0 explicitly.

Example fix

// before
<halftoneLinearGradient firstStopDotSize={spring.value - 4} />
// spring can drop below 4 -> negative

// after
<halftoneLinearGradient firstStopDotSize={Math.max(0, spring.value - 4)} />
Defensive patterns

Strategy: validation

Validate before calling

const clampDotSize = (v: number | undefined): number =>
  Math.max(0, v ?? 0);
params.firstStopDotSize = clampDotSize(params.firstStopDotSize);
params.secondStopDotSize = clampDotSize(params.secondStopDotSize);

Type guard

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

Try / catch

null

Prevention

When it happens

Trigger: validateHalftoneLinearGradientParams runs validateNonNegative on firstStopDotSize (line 252) and secondStopDotSize (line 256) when those params are provided. Triggered by passing either stop's dot size as a negative finite number.

Common situations: A spring/interpolation dipping below zero; deriving dot size from an offset that goes negative; a sign typo; reusing a value calibrated for a different effect whose range differs.

Related errors


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