remotion-dev/remotion · error · TypeError

A numeric bitrate must be a positive integer.

Error message

A numeric bitrate must be a positive integer.

What it means

resolveVideoMattingQuality converts a VideoMattingBitrate into a Quality. When the caller passes a number, it must be a positive integer bitrate in bits per second; non-integers, zero, negative values, NaN or Infinity are rejected with a TypeError. This ensures the underlying encoder receives a valid bitrate.

Source

Thrown at packages/video-matting/src/video-matting-quality.ts:20

export const VIDEO_MATTING_QUALITIES = [
	'very-low',
	'low',
	'medium',
	'high',
	'very-high',
] as const;

export type VideoMattingQuality = (typeof VIDEO_MATTING_QUALITIES)[number];

export type VideoMattingBitrate = number | VideoMattingQuality;

export const resolveVideoMattingQuality = (
	value: VideoMattingBitrate,
): Quality => {
	if (typeof value === 'number') {
		if (!Number.isInteger(value) || value <= 0) {
			throw new TypeError('A numeric bitrate must be a positive integer.');
		}

		return new Quality({bitrate: value});
	}

	if (!VIDEO_MATTING_QUALITIES.includes(value)) {
		throw new TypeError(
			`The bitrate quality must be one of ${VIDEO_MATTING_QUALITIES.join(', ')}.`,
		);
	}

	return new Quality({quality: value, preferBitrate: true});
};

View on GitHub (pinned to b2f4e34732)

Solutions

  1. Pass a positive integer, e.g. 4_000_000 instead of 4e6/3 or 0
  2. Round and validate dynamic bitrates: Math.round(computed) and check > 0 before calling
  3. Use a named quality preset ('low' | 'medium' | 'high') instead of a raw number if unsure
  4. Fix config parsing so unset/0 values fall back to a default rather than being passed as bitrate

Example fix

// before
const q = resolveVideoMattingQuality(bitrateFromConfig); // 0 or 3.5
// after
const bitrate = Math.round(Number(bitrateFromConfig));
if (!Number.isInteger(bitrate) || bitrate <= 0) throw new Error('Invalid bitrate in config');
const q = resolveVideoMattingQuality(bitrate);
Defensive patterns

Strategy: validation

Validate before calling

const isValidBitrate = (v: unknown): v is number =>
  typeof v === 'number' && Number.isInteger(v) && v > 0;
if (!isValidBitrate(bitrate)) throw new TypeError(`Invalid bitrate: ${bitrate}`);

Type guard

const isNumericBitrate = (v: VideoMattingBitrate): v is number =>
  typeof v === 'number';
const isValidNumericBitrate = (v: VideoMattingBitrate): v is number =>
  typeof v === 'number' && Number.isInteger(v) && v > 0;

Try / catch

try {
  const quality = resolveVideoMattingQuality(bitrate);
} catch (err) {
  if (err instanceof TypeError && err.message.includes('positive integer')) {
    return resolveVideoMattingQuality(4_000_000); // sensible default
  }
  throw err;
}

Prevention

When it happens

Trigger: Passing a number bitrate like 0, -5000, 3.5, NaN or Infinity to resolveVideoMattingQuality — typically via a videoMatting quality/bitrate option in the render or component API.

Common situations: Computing a bitrate dynamically (e.g. width * height * factor) producing a float, a config value of 0 meaning 'unset' being passed through, or parsing a user-supplied string with parseFloat instead of parseInt.

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/1d3ebd75bfbec5e9. Report an issue: GitHub.