remotion-dev/remotion · error
Failed to create output canvas context
Error message
Failed to create output canvas context
What it means
In @remotion/transitions' HTML-in-canvas presentation, clearOutput obtains a 2D rendering context from the output canvas via getContext('2d') to clear it between draws. If the browser returns null — no 2D context can be created — this error is thrown inside the onPaint delayRender scope. This typically means the canvas is already bound to a different context type or the canvas cannot provide a context at all.
Source
Thrown at packages/transitions/src/html-in-canvas-presentation.tsx:120
};
}, [instance]);
const chainState = Internals.useEffectChainState();
const {delayRender, continueRender, cancelRender} = useDelayRender();
const draw: DrawFunction = useCallback(
async (prevImage, nextImage, progress) => {
const outputCanvas = outputCanvasRef.current;
if (!outputCanvas) {
throw new Error('Canvas not found');
}
const handle = delayRender('onPaint');
try {
const clearOutput = () => {
const context = outputCanvas.getContext('2d');
if (!context) {
throw new Error('Failed to create output canvas context');
}
context.clearRect(0, 0, outputCanvas.width, outputCanvas.height);
};
if (!prevImage && !nextImage) {
instance.clear();
clearOutput();
continueRender(handle);
return;
}
const width = prevImage?.width ?? nextImage?.width ?? 0;
const height = prevImage?.height ?? nextImage?.height ?? 0;
if (width === 0 || height === 0) {
instance.clear();
clearOutput();View on GitHub (pinned to a6a7485a9a)
Solutions
- Ensure nothing else calls getContext with a non-2d type on the same outputCanvas; give the presentation its own dedicated canvas element
- Create a fresh canvas for the presentation instead of reusing one from elsewhere in the app
- Verify the code runs in a browser with a real DOM document (not SSR) and the canvas is attached/has non-zero width/height
- Enable GPU/hardware acceleration (or add --enable-unsafe-swiftshader / software GL flags) in headless Chrome if context creation fails there
- Wrap the paint work so the error surfaces with the delayRender handle properly released (use continueRender in a catch/finally) to avoid a stuck render
Example fix
// before
const context = outputCanvas.getContext('2d'); // null if canvas already used for webgl
if (!context) throw new Error('Failed to create output canvas context');
// after
const outputCanvas = document.createElement('canvas'); // dedicated canvas, never handed to webgl
const context = outputCanvas.getContext('2d');
if (!context) throw new Error('Failed to create output canvas context'); Defensive patterns
Strategy: try-catch
Validate before calling
function canProvide2DContext(canvas: HTMLCanvasElement): boolean {
// A canvas can only ever yield one context type; probe safely by checking existing state.
return canvas instanceof HTMLCanvasElement && canvas.width > 0 && canvas.height > 0;
} Type guard
function has2DContext(canvas: HTMLCanvasElement): canvas is HTMLCanvasElement & { getContext: (t: '2d') => CanvasRenderingContext2D } {
return canvas.getContext('2d') !== null;
} Try / catch
const handle = delayRender('onPaint');
try {
const context = outputCanvas.getContext('2d');
if (!context) throw new Error('Failed to create output canvas context');
context.clearRect(0, 0, outputCanvas.width, outputCanvas.height);
continueRender(handle);
} catch (err) {
continueRender(handle);
console.error('Canvas 2D context unavailable; use a fresh dedicated canvas.', err);
} Prevention
- Never call getContext('2d') on a canvas that has been used with webgl, webgpu, or bitmaprenderer — allocate a separate canvas per context type
- Create the output canvas with document.createElement and attach it to the DOM before painting
- Ensure rendering happens in a real browser context (no SSR) with hardware acceleration or software-GL available in headless Chrome
- Always pair delayRender with continueRender in finally so a context failure cannot hang the render forever
When it happens
Trigger: Calling getContext('2d') on a canvas that previously had getContext('webgl'/'bitmaprenderer') called on it (a canvas returns null for all other context types after the first); passing a detached/off-DOM or zero-sized canvas in an environment without a real document; browser failing context creation under memory pressure.
Common situations: Mixing the transitions canvas presentation with other code (three.js, WebGL preview) that grabbed a different context on the same canvas element; rendering headless (server-side) where the canvas is not backed by a document; hardware-acceleration disabled in the rendering browser causing 2D context creation to fail.
Related errors
- The browser threw an error
- Failed to acquire 2D context for color parsing
- Failed to create WebGL texture
- The display canvas would be ${displayWidth}×${displayHeight}
- Should not download a browser in Cloud Run
AI-assisted analysis of remotion-dev/remotion@a6a7485a9a (2026-09-02).
Data as JSON: /api/errors/b4fda24c553bf3cf.
Report an issue: GitHub.