remotion-dev/remotion · error · Error

Canvas capture scale must be greater than 0.

Error message

Canvas capture scale must be greater than 0.

What it means

At `startRecording`, after disposal/recording guards, the recorder reads `this.#options.getDensity()` and requires it to be a finite positive number. Non-finite values (NaN/Infinity) and values <= 0 are rejected before importing Mediabunny and creating the BufferTarget. The density drives the capture scale, so zero/negative scale is meaningless.

Source

Thrown at packages/canvas-capture-extension/src/recorder.ts:416

		window.addEventListener('dragover', this.#onCursorMove, true);
		window.addEventListener('pointerdown', this.#onPointerDown, true);
		window.addEventListener('pointerup', this.#onPointerUp, true);
	}

	isRecording = () => this.#recording !== null;

	startRecording = async () => {
		if (this.#disposed) {
			throw new Error('This canvas recorder has already been disposed.');
		}

		if (this.#recording) {
			return;
		}

		const density = this.#options.getDensity();
		if (!Number.isFinite(density) || density <= 0) {
			throw new Error('Canvas capture scale must be greater than 0.');
		}

		const {
			BufferTarget,
			Mp4OutputFormat,
			Output,
			QUALITY_HIGH,
			VideoSample,
			VideoSampleSource,
			WebMOutputFormat,
		} = await import('mediabunny');
		const target = new BufferTarget();
		const output = new Output({
			format:
				this.#options.format === 'mp4'
					? new Mp4OutputFormat()
					: new WebMOutputFormat(),
			target,

View on GitHub (pinned to 78fe4bb3fd)

Solutions

  1. Provide a density/scale > 0 (typically 1 for 1x, 2 for retina).
  2. Validate the density with `Number.isFinite(d) && d > 0` before starting.
  3. Clamp user input to a positive minimum (e.g., 0.1).
  4. Check the option provider (`getDensity`) returns a sane default.

Example fix

// before
const recorder = new CanvasCaptureRecorder({getDensity: () => 0});
await recorder.startRecording();

// after
const recorder = new CanvasCaptureRecorder({getDensity: () => 1});
await recorder.startRecording();
Defensive patterns

Strategy: validation

Validate before calling

function validDensity(d: unknown): d is number {
  return typeof d === 'number' && Number.isFinite(d) && d > 0;
}
// before startRecording:
const d = options.getDensity();
if (!validDensity(d)) throw new Error('Density must be a positive finite number.');

Type guard

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

Try / catch

try {
  await recorder.startRecording();
} catch (e) {
  if (e instanceof Error && /scale must be greater than 0/.test(e.message)) {
    options.setDensity(1);
    await recorder.startRecording();
  } else throw e;
}

Prevention

When it happens

Trigger: Passing a scale/density option of 0, a negative number, NaN, or Infinity to the recorder; a UI control defaulting to 0; parsing a user-entered scale that fails `Number.isFinite`.

Common situations: A scale slider initialized to 0; empty/invalid input parsed to NaN; copied config with a missing density field defaulting improperly; Infinity from a divide-by-zero in density computation.

Related errors


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