remotion-dev/remotion · error · TypeError

"${name}" must be greater than or equal to 0, but got ${JSON

Error message

"${name}" must be greater than or equal to 0, but got ${JSON.stringify(value)}

What it means

Thrown by validateNonNegative() during waves() effect param validation. The waves effect requires gap and amplitude to be non-negative (>= 0). This TypeError fires when either value is negative after applying defaults. The error message names which field is invalid and shows the offending value.

Source

Thrown at packages/effects/src/waves.ts:219

	}

	return `${variants
		.slice(0, -1)
		.map((variant) => `"${variant}"`)
		.join(', ')} or "${variants[variants.length - 1]}"`;
};

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 validateNonNegative = (value: number, name: string): void => {
	if (value < 0) {
		throw new TypeError(
			`"${name}" must be greater than or equal to 0, but got ${JSON.stringify(value)}`,
		);
	}
};

const validateColors = (colors: unknown): void => {
	if (colors === undefined) {
		return;
	}

	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)}`,
		);
	}

	for (let i = 0; i < colors.length; i++) {
		assertRequiredColor(colors[i], `colors[${i}]`);

View on GitHub (pinned to 78fe4bb3fd)

Solutions

  1. Clamp the animated value with Math.max(0, value) before passing it.
  2. Use waves({gap: 0}) instead of a negative value if you want no gap.
  3. Use waves({amplitude: 0}) for a flat (non-wavy) stripe pattern.
  4. Check that easing/spring configs don't overshoot into negative territory for these params.

Example fix

// before
import {waves} from '@remotion/effects';
waves({gap: -10})       // throws
waves({amplitude: -5})  // throws

// after
waves({gap: 0})         // no gap
waves({amplitude: 0})   // flat stripes

// animating with a safe clamp
waves({
  amplitude: Math.max(0, interpolate(frame, [0, 30], [0, 50])),
})
Defensive patterns

Strategy: validation

Validate before calling

import type {WavesParams} from '@remotion/effects';

const validateWavesNonNegative = (params: WavesParams): void => {
  if (params.gap !== undefined && params.gap < 0) {
    throw new Error(`gap must be >= 0, got ${params.gap}`);
  }
  if (params.amplitude !== undefined && params.amplitude < 0) {
    throw new Error(`amplitude must be >= 0, got ${params.amplitude}`);
  }
};

validateWavesNonNegative({gap: myGap, amplitude: myAmplitude});

Type guard

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

const hasValidNonNegativeParams = (params: {
  gap?: number;
  amplitude?: number;
}): boolean =>
  (params.gap === undefined || isNonNegativeNumber(params.gap)) &&
  (params.amplitude === undefined || isNonNegativeNumber(params.amplitude));

Prevention

When it happens

Trigger: Called from validateWavesParams() at packages/effects/src/waves.ts:275 (validateNonNegative(gap, 'gap')) and line 276 (validateNonNegative(amplitude, 'amplitude')). Fires when you pass waves({gap: -1}) or waves({amplitude: -5}). Defaults are gap=0 and amplitude=24, so this only triggers on explicit negative values.

Common situations: Passing a negative gap or amplitude from an animation expression that overshoots below zero; accidentally using a signed offset value for gap; interpolating amplitude through a negative range during a spring/easing overshoot.

Related errors


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