remotion-dev/remotion · error · RangeError

Argument for frame must be an integer, but got ${frame}

Error message

Argument for frame must be an integer, but got ${frame}

What it means

validateFrame throws a RangeError when frame is a non-integer (has a fractional part) and the caller did not enable `allowFloats`. Most Remotion APIs operate on integer frame indices; floating-point frames are only valid in specific sub-APIs that pass allowFloats=true.

Source

Thrown at packages/core/src/validate-frame.ts:25

	durationInFrames: number;
	allowFloats: boolean;
}) => {
	if (typeof frame === 'undefined') {
		throw new TypeError(`Argument missing for parameter "frame"`);
	}

	if (typeof frame !== 'number') {
		throw new TypeError(
			`Argument passed for "frame" is not a number: ${frame}`,
		);
	}

	if (!Number.isFinite(frame)) {
		throw new RangeError(`Frame ${frame} is not finite`);
	}

	if (frame % 1 !== 0 && !allowFloats) {
		throw new RangeError(
			`Argument for frame must be an integer, but got ${frame}`,
		);
	}

	if (frame < 0 && frame < -durationInFrames) {
		throw new RangeError(
			`Cannot use frame ${frame}: Duration of composition is ${durationInFrames}, therefore the lowest frame that can be rendered is ${-durationInFrames}`,
		);
	}

	if (frame > durationInFrames - 1) {
		throw new RangeError(
			`Cannot use frame ${frame}: Duration of composition is ${durationInFrames}, therefore the highest frame that can be rendered is ${
				durationInFrames - 1
			}`,
		);
	}
};

View on GitHub (pinned to 78fe4bb3fd)

Solutions

  1. Round to the nearest integer: `Math.round(frame)` or `Math.floor(frame)` before passing.
  2. If you genuinely need sub-frame precision, use an API path that passes allowFloats=true (interpolation inputs).
  3. Sanitize floating-point: `Math.round(frame * 1e6) / 1e6` to kill rounding dust, then round.
  4. Confirm which API you are calling — most player/timeline calls want integers.

Example fix

// before
const frame = timeSeconds * fps; // 12.5
seekTo(frame);

// after
const frame = Math.round(timeSeconds * fps);
seekTo(frame);
Defensive patterns

Strategy: validation

Validate before calling

const intFrame = Math.round(frame);
validateFrame({ frame: intFrame, durationInFrames, allowFloats });

Type guard

const isIntegerFrame = (f: unknown): f is number => typeof f === 'number' && Number.isInteger(f);

Prevention

When it happens

Trigger: Passing a float (e.g. 12.5) to an integer-only API like seekTo or timeline registration without allowFloats; computing frame from sub-frame math; rounding errors leaving a tiny fractional component like 12.0000000001.

Common situations: Interpolating/extrapolating to a frame and forgetting to round; dividing time by fps yielding a fractional frame; mixing continuous-time APIs with integer-frame APIs.

Related errors


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