remotion-dev/remotion · error · Error

Could not create a 2D canvas context.

Error message

Could not create a 2D canvas context.

What it means

canvas.getContext('2d', {willReadFrequently: true}) returned null, so no 2D rendering context could be created for the matting canvas. The library needs pixel readback (willReadFrequently) to run the matting model and draw output frames; without a 2D context it cannot proceed and throws.

Source

Thrown at packages/video-matting/src/video-matting-canvas.ts:37

	if (typeof document !== 'undefined') {
		const canvas = document.createElement('canvas');
		canvas.width = width;
		canvas.height = height;
		return canvas;
	}

	throw new Error(
		'Could not create a canvas. This API must run in a browser with OffscreenCanvas or the DOM available.',
	);
};

export const getVideoMattingCanvasContext = (
	canvas: VideoMattingCanvas,
): VideoMattingCanvasContext => {
	const context = canvas.getContext('2d', {willReadFrequently: true});
	if (!context) {
		throw new Error('Could not create a 2D canvas context.');
	}

	return context as VideoMattingCanvasContext;
};

export const drawOpaqueBaseFrame = ({
	context,
	source,
	width,
	height,
}: {
	context: VideoMattingCanvasContext;
	source: VideoMattingCanvas;
	width: number;
	height: number;
}) => {
	context.save();
	context.globalCompositeOperation = 'copy';

View on GitHub (pinned to b2f4e34732)

Solutions

  1. Free finished work: null out references to prior canvases/contexts so the browser can reclaim contexts.
  2. Don't call getContext('webgl'/'webgpu') on canvases managed by this library.
  3. Catch the error and retry once with a fresh OffscreenCanvas if the context limit was transient.
  4. Reduce concurrent separateVideoLayers calls so fewer canvases exist at once.

Example fix

// before
const ctx = sharedCanvas.getContext('webgl'); // poisons future 2d requests downstream
await separateVideoLayers({src});
// after
const ctx = sharedCanvas.getContext('2d');
await separateVideoLayers({src});
Defensive patterns

Strategy: try-catch

Validate before calling

const test = document.createElement('canvas');
if (!test.getContext('2d')) {
  throw new Error('This environment cannot create a 2D canvas context');
}

Try / catch

try {
  await separateVideoLayers({src});
} catch (e) {
  if (e instanceof Error && e.message.includes('2D canvas context')) {
    // likely too many live canvases or a poisoned canvas — retry after cleanup
    releaseCanvases();
    return separateVideoLayers({src});
  }
  throw e;
}

Prevention

When it happens

Trigger: Requesting a '2d' context from a canvas that already yielded a different context type ('webgl'/'webgpu'); browser limits on total number of canvas contexts being exhausted (too many canvases alive); a context lost due to GPU constraints; canvas of zero size in some engines.

Common situations: Mixing the library with code that previously grabbed a WebGL context on the same canvas (rare, since the library creates its own); pages creating hundreds of canvases until the browser's context limit is hit; GPU-driver crashes marking contexts lost in long-running sessions.

Understand the failure class

Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.

Related errors


AI-assisted analysis of remotion-dev/remotion@b2f4e34732 (2026-09-09). Data as JSON: /api/errors/8f3d36bd92c55b76. Report an issue: GitHub.