remotion-dev/remotion · error · Error

Failed to create WebGL framebuffer

Error message

Failed to create WebGL framebuffer

What it means

Thrown by setupDropShadow when gl.createFramebuffer() returns null. A null framebuffer indicates a lost or resource-exhausted WebGL2 context. The drop-shadow runtime uses offscreen framebuffers for the extract and two blur passes, so the allocation must succeed before any rendering.

Solutions

  1. Confirm cleanupDropShadow runs (gl.deleteFramebuffer on unmount).
  2. Reduce simultaneous drop-shadow effects or composition resolution.
  3. Reload to free leaked framebuffers; update GPU drivers.
  4. For headless/CI, use SwiftShader with sufficient memory and limit concurrency.
Defensive patterns

Strategy: try-catch

Validate before calling

const supportsWebGL2 = () => {
  try {
    return !!document.createElement('canvas').getContext('webgl2');
  } catch {
    return false;
  }
};

Try / catch

try {
  state = setupDropShadow(canvas);
} catch (err) {
  if (err instanceof Error && /WebGL framebuffer/i.test(err.message)) {
    console.error('Drop-shadow framebuffer allocation failed:', err.message);
    // fall back to a CSS box-shadow layer
  } else {
    throw err;
  }
}

Prevention

When it happens

Trigger: Lost WebGL2 context, exhausted framebuffer object limit, or GPU memory pressure. Reached inside setupDropShadow() after textures are allocated, when the render-target framebuffer is created.

Common situations: Framebuffer leaks from effects whose cleanup was skipped; many simultaneous drop-shadow effects; GPU driver crash; headless rendering under memory pressure; VMs with passthrough GL.

Related errors


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

Appendix: source

Thrown at packages/effects/src/drop-shadow/drop-shadow-runtime.ts:196

	}

	gl.bindBuffer(gl.ARRAY_BUFFER, vbo);
	gl.bufferData(gl.ARRAY_BUFFER, data, gl.STATIC_DRAW);

	gl.enableVertexAttribArray(0);
	gl.vertexAttribPointer(0, 2, gl.FLOAT, false, 16, 0);
	gl.enableVertexAttribArray(1);
	gl.vertexAttribPointer(1, 2, gl.FLOAT, false, 16, 8);

	gl.bindVertexArray(null);

	const textureSource = createRgbaTexture(gl);
	const textureShadowA = createRgbaTexture(gl);
	const textureShadowB = createRgbaTexture(gl);

	const framebuffer = gl.createFramebuffer();
	if (!framebuffer) {
		throw new Error('Failed to create WebGL framebuffer');
	}

	const colorCanvas = document.createElement('canvas');
	colorCanvas.width = 1;
	colorCanvas.height = 1;
	const colorCtx = colorCanvas.getContext('2d', {willReadFrequently: true});
	if (!colorCtx) {
		throw new Error('Failed to acquire 2D context for color parsing');
	}

	return {
		gl,
		programExtract,
		programHorizontal,
		programVertical,
		programComposite,
		vao,
		vbo,

View on GitHub (pinned to 78fe4bb3fd)