remotion-dev/remotion · error

"progress" must be >= 0

Error message

"progress" must be >= 0

What it means

The <Tear> effect validates its parameters before rendering. `progress` controls how far the tear has ripped (0 = intact; values above 1 push the pieces farther apart). After substituting defaults, the effect throws if the resolved progress is negative, since a negative progress is meaningless. Note the check runs on the RESOLVED value, so passing undefined is fine (defaults to 0.5) but explicitly passing a negative number fails.

Source

Thrown at packages/effects/src/tear.ts:75

	readonly jaggedness?: number;
};

const resolve = (p: TearParams) => ({
	progress: p.progress ?? DEFAULT_PROGRESS,
	angle: p.angle ?? DEFAULT_ANGLE,
	rotation: p.rotation ?? DEFAULT_ROTATION,
	jaggedness: p.jaggedness ?? DEFAULT_JAGGEDNESS,
});

const validateTearParams = (params: TearParams): void => {
	assertEffectParamsObject(params, 'Tear');
	assertOptionalFiniteNumber(params.progress, 'progress');
	assertOptionalFiniteNumber(params.angle, 'angle');
	assertOptionalFiniteNumber(params.rotation, 'rotation');
	assertOptionalFiniteNumber(params.jaggedness, 'jaggedness');
	const r = resolve(params);
	if (r.progress < 0) {
		throw new Error('"progress" must be >= 0');
	}

	if (r.rotation < 0 || r.rotation > 90) {
		throw new Error('"rotation" must be between 0 and 90');
	}

	if (r.jaggedness < 0) {
		throw new Error('"jaggedness" must be >= 0');
	}
};

type TearState = {
	readonly gl: WebGL2RenderingContext;
	readonly program: WebGLProgram;
	readonly vao: WebGLVertexArrayObject;
	readonly vbo: WebGLBuffer;
	readonly texture: WebGLTexture;
	readonly uSource: WebGLUniformLocation | null;

View on GitHub (pinned to b2f4e34732)

Solutions

  1. Clamp progress to >= 0 before passing it: Math.max(0, value).
  2. If using interpolate(), set extrapolateLeft: 'clamp' so early frames do not produce negative values.
  3. Check the frame math driving the animation — ensure the range start is not before the animation begins.
  4. Verify the literal value: a negative sign may be a typo (progress={-1} vs progress={1}).

Example fix

// before
<Tear progress={frame / durationInFrames} />

// after
<Tear
  progress={Math.max(0, frame / durationInFrames)}
/>
Defensive patterns

Strategy: validation

Validate before calling

if (progress !== undefined && (!Number.isFinite(progress) || progress < 0)) {
  throw new RangeError(`progress must be >= 0, got ${progress}`);
}

Try / catch

try {
  return <Tear progress={p} ... />;
} catch (e) {
  if (e instanceof Error && e.message.includes('"progress" must be >= 0')) {
    return <Tear progress={Math.max(0, p)} ... />;
  }
  throw e;
}

Prevention

When it happens

Trigger: Calling <Tear progress={-0.1}> (or any negative number), or animating progress from a value that dips below 0, e.g. spring()/interpolate() output that undershoots (overshoot clamping disabled), or passing a NaN-adjacent calculation result that resolves negative after the finite-number assertion.

Common situations: Driving progress from a spring with damping that swings negative at the start; computing progress as (frame - startFrame)/duration where the frame is before startFrame; typo in a constant like progress={-1} intending 1.

Understand the failure class

Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.

Related errors


AI-assisted analysis of remotion-dev/remotion@b2f4e34732 (2026-09-09). Data as JSON: /api/errors/df9f476d13740a9b. Report an issue: GitHub.