remotion-dev/remotion · error · Error

No canvas recording was available to open.

Error message

No canvas recording was available to open.

What it means

Thrown by `CaptureSession.stop()` after `this.#recorder.stopRecording()` resolves to a falsy file. Before throwing, the recorder flushes any pending paint error and runs a final `#draw()`. The `finally` block calls `this.restore()`, so the wrapped page is always unwound. A null/undefined file means the recorder produced no output blob.

Source

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

			this.#wrapped.canvas,
			width,
			height,
			window.devicePixelRatio,
		);
		await this.#recorder.startRecording();
		this.#requestPaint();
	};

	stop = async () => {
		try {
			if (this.#paintError) {
				throw this.#paintError;
			}

			this.#draw();
			const file = await this.#recorder.stopRecording();
			if (!file) {
				throw new Error('No canvas recording was available to open.');
			}

			return file;
		} finally {
			this.restore();
		}
	};

	restore = () => {
		if (this.#restored) {
			return;
		}

		this.#restored = true;
		this.#resizeObserver.disconnect();
		this.#wrapped.canvas.removeEventListener('paint', this.#onPaint);
		this.#recorder.dispose();
		this.#wrapped.restore();

View on GitHub (pinned to 78fe4bb3fd)

Solutions

  1. Ensure at least one frame is captured before calling `stop()` — wait for a paint or a timeout.
  2. Check `this.#paintError` was not set; if it was, the underlying paint failure is the root cause.
  3. Do not call `stop()` twice or after `restore()`/dispose.
  4. If the recorder returns no file persistently, inspect Mediabunny encoding errors surfaced via `recording.encodingError`.
Defensive patterns

Strategy: validation

Validate before calling

// Ensure at least one frame is drawn before stopping.
async function safeStop(rec: {stop: () => Promise<File | null>}, drewFrame: boolean) {
  if (!drewFrame) throw new Error('Wait for at least one frame before stopping.');
  return rec.stop();
}

Try / catch

try {
  const file = await session.stop();
} catch (e) {
  if (e instanceof Error && /No canvas recording was available/.test(e.message)) {
    await waitForNextPaint();
    // do NOT blindly retry; re-arm the session instead.
  }
  throw e;
}

Prevention

When it happens

Trigger: Calling `stop()` immediately after `start()` before any frames were drawn; the recorder's `finalizeRecording` returned null/undefined (e.g., Mediabunny produced no buffer and that path returned falsy); the recorder was already stopped or disposed so no new file is produced.

Common situations: Start/stop called in rapid succession with no paint cycles between them; capture started but the page never repainted; a prior error path left the recorder in a state where `stopRecording()` resolves empty.

Related errors


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