remotion-dev/remotion · critical · Error

Failed to create WebGL shader

Error message

Failed to create WebGL shader

What it means

Thrown by gridlines' compileShader (gridlines.ts:365) when gl.createShader(type) returns null. A null return means WebGL could not allocate a shader object, typically due to context loss or severe GPU resource exhaustion. The library throws immediately because subsequent shaderSource/compileShader calls would crash on null.

Source

Thrown at packages/effects/src/gridlines.ts:365

	vec4 line = uLineColor * coverage;

	if (uMaskToSourceAlpha) {
		fragColor = sourceAtop(sourceAtop(texColor, background), line);
		return;
	}

	fragColor = sourceOver(sourceOver(texColor, background), line);
}
`;

const compileShader = (
	gl: WebGL2RenderingContext,
	type: number,
	source: string,
): WebGLShader => {
	const shader = gl.createShader(type);
	if (!shader) {
		throw new Error('Failed to create WebGL shader');
	}

	gl.shaderSource(shader, source);
	gl.compileShader(shader);
	if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
		const log = gl.getShaderInfoLog(shader);
		gl.deleteShader(shader);
		throw new Error(`Gridlines shader compile failed: ${log ?? '(no log)'}`);
	}

	return shader;
};

const linkProgram = (
	gl: WebGL2RenderingContext,
	vs: WebGLShader,
	fs: WebGLShader,
): WebGLProgram => {

View on GitHub (pinned to 78fe4bb3fd)

Solutions

  1. Check the WebGL context for loss: register a webglcontextlost listener on the canvas and recreate the effect on restore.
  2. Reduce the number of concurrent WebGL effects/compositions; ensure cleanup() is called so GL objects are freed.
  3. Restart the headless browser/GPU; if persistent, update GPU drivers or switch ANGLE backend.
  4. Confirm you are not creating new canvases/contexts in a render loop without disposing them.

Example fix

// before: a new effect/canvas per frame with no cleanup -> eventual null allocation
useEffect(() => { makeEffect(); }, [frame]);

// after: set up once, clean up on unmount, handle context loss
useEffect(() => {
  const canvas = ref.current!;
  const onLost = (e: Event) => { e.preventDefault(); /* recreate */ };
  canvas.addEventListener('webglcontextlost', onLost);
  const handle = setupOnce();
  return () => { handle.cleanup(); canvas.removeEventListener('webglcontextlost', onLost); };
}, []);
Defensive patterns

Strategy: try-catch

Validate before calling

// Probe context health before relying on GL allocation
const lost = gl.isContextLost();
if (lost) throw new Error('WebGL2 context lost before shader allocation');

Type guard

null

Try / catch

try {
  gridlines.setup(canvas);
} catch (e) {
  if (e instanceof Error && e.message === 'Failed to create WebGL shader') {
    // context loss / resource exhaustion: recreate context, reduce load
  }
  throw e;
}

Prevention

When it happens

Trigger: Called during the Gridlines effect setup, after acquiring a WebGL2 context, for both the vertex and fragment shaders. Happens when the WebGL context is lost (e.g. GPU driver crash, too many contexts), the process has leaked GL objects, or the driver refuses new shader allocation.

Common situations: Long-running render that leaks contexts; multiple Studio previews/compositions open exhausting the GPU; a machine hitting a GPU-reset/context-loss; running on a driver/SwiftShader that caps shader count.

Related errors


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