remotion-dev/remotion · error · Error

No frames were added to the canvas recording.

Error message

No frames were added to the canvas recording.

What it means

Inside `finalizeRecording`, after awaiting the last frame and checking `hasEncodingError`, the code requires `recording.frameCount` to be non-zero. A zero frame count means no `VideoSample` was ever pushed into the Mediabunny source, so there is nothing to encode. Thrown before closing the source and finalizing output.

Solutions

  1. Ensure at least one frame is added before stopping — wait for a paint cycle or a fixed delay.
  2. Verify the page is animating/repainting so the draw loop pushes frames.
  3. Check for and surface `this.#paintError` before stopping.
  4. Do not stop a recorder that never started drawing.
Defensive patterns

Strategy: validation

Validate before calling

let frameCount = 0;
const onFrame = () => { frameCount++; };
// before stopping:
if (frameCount === 0) throw new Error('No frames captured yet; wait for a paint.');

Try / catch

try {
  await recorder.stopRecording();
} catch (e) {
  if (e instanceof Error && /No frames were added/.test(e.message)) {
    await waitForPaint();
    // restart session rather than retrying the same one.
  }
  throw e;
}

Prevention

When it happens

Trigger: Stopping the recorder before any frame was drawn/added; the draw loop never fired because the page never repainted; the recorder started but `#draw()` was never invoked before `stopRecording()`.

Common situations: Start immediately followed by stop; capturing a static page that does not request animation frames; an earlier paint error prevented frames from being added but did not set `hasEncodingError`.

Related errors


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

Appendix: source

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

		} finally {
			recording.isEncodingFrame = false;
		}
	})();
	recording.lastFramePromise.catch(() => undefined);
};

const finalizeRecording = async (
	recording: RecordingState,
	filename: string,
	format: CaptureFormat,
): Promise<File> => {
	await recording.lastFramePromise;
	if (recording.hasEncodingError) {
		throw recording.encodingError;
	}

	if (recording.frameCount === 0) {
		throw new Error('No frames were added to the canvas recording.');
	}

	recording.source.close();
	await recording.output.finalize();

	if (!recording.target.buffer) {
		throw new Error('Mediabunny did not return an output buffer.');
	}

	const captureData = JSON.stringify({
		startedAt: recording.startedAt,
		endedAt: performance.now(),
		captureMetadata: recording.captureMetadata,
		mouseMovements: recording.mouseMovements,
		pointerClicks: recording.pointerClicks,
	});

	const {

View on GitHub (pinned to 78fe4bb3fd)