remotion-dev/remotion · error · TypeError

"stops" must be >= ${MIN_STOPS}, but got ${JSON.stringify(st

Error message

"stops" must be >= ${MIN_STOPS}, but got ${JSON.stringify(stops)}

What it means

Thrown by validateExposureParams() in exposure.ts when the resolved `stops` value is below MIN_STOPS (-5). It is a TypeError fired during the effect's validateParams step, before any WebGL work, so the user gets fast, deterministic feedback. The offending value is JSON-stringified into the message.

Source

Thrown at packages/effects/src/exposure.ts:56

	readonly vbo: WebGLBuffer;
	readonly textureSource: WebGLTexture;
	readonly uniforms: {
		readonly uSource: WebGLUniformLocation | null;
		readonly uStops: WebGLUniformLocation | null;
	};
};

const resolve = (params: ExposureParams): ExposureResolved => ({
	stops: params.stops ?? DEFAULT_STOPS,
});

const validateExposureParams = (params: ExposureParams): void => {
	assertEffectParamsObject(params, 'Exposure');
	assertOptionalFiniteNumber(params.stops, 'stops');

	const {stops} = resolve(params);
	if (stops < MIN_STOPS) {
		throw new TypeError(
			`"stops" must be >= ${MIN_STOPS}, but got ${JSON.stringify(stops)}`,
		);
	}

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

const VERTEX_SHADER = /* glsl */ `#version 300 es
in vec2 aPos;
in vec2 aUv;
out vec2 vUv;

void main() {
	vUv = aUv;

View on GitHub (pinned to 78fe4bb3fd)

Solutions

  1. Clamp the animated value to [-5, 5] before passing it: exposure({ stops: Math.max(-5, Math.min(5, value)) }).
  2. Inspect the easing/interpolation for overshoot and pick an easing that stays in range (e.g. linear or ease-in-out without spring overshoot).
  3. Validate the source data feeding stops and reject or clamp values outside [-5, 5] upstream.
  4. If you genuinely need more than ±5 stops, layer two exposure() effects or request a wider range from the effect maintainer.

Example fix

// before
exposure({ stops: springValue }); // spring overshoots to -5.4 -> throws

// after
exposure({ stops: Math.max(-5, Math.min(5, springValue)) });
Defensive patterns

Strategy: validation

Validate before calling

// Clamp before passing to exposure(); range is [-5, 5] (MIN_STOPS..MAX_STOPS).
const EXPOSURE_STOPS_MIN = -5;
const EXPOSURE_STOPS_MAX = 5;

const clampStops = (stops: number): number =>
  Math.max(EXPOSURE_STOPS_MIN, Math.min(EXPOSURE_STOPS_MAX, stops));

// usage: exposure({ stops: clampStops(animatedValue) })

Type guard

const isExposureStops = (v: unknown): v is number =>
  typeof v === 'number' &&
  Number.isFinite(v) &&
  v >= -5 &&
  v <= 5;

// guard: if (isExposureStops(value)) exposure({ stops: value }); else /* clamp or skip */

Prevention

When it happens

Trigger: Calling exposure({ stops: x }) with x < -5 (e.g. exposure({ stops: -6 }), or a NaN that slipped past assertOptionalFiniteNumber only if the finite-number guard was bypassed). Resolution applies the DEFAULT_STOPS (0) only when stops is undefined; any provided number below -5 trips this branch.

Common situations: Animations interpolating stops with a curve that overshoots past -5 (e.g. an easing that briefly hits -5.5); reading stops from a data file or control that allows out-of-range values; passing a negativeInfinity by mistake; UI slider with a wider range than the schema enforces.

Related errors


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