remotion-dev/remotion · critical · Error

Failed to create WebGL shader

Error message

Failed to create WebGL shader

What it means

While setting up the mirror effect's WebGL2 pipeline, compileShader called gl.createShader() which returned null instead of a WebGLShader handle. The WebGL2 context exists (an earlier check would have thrown createWebGL2ContextError) but is in an unhealthy state — most commonly due to context loss, GPU resource exhaustion, or a headless environment with inadequate GPU drivers.

Source

Thrown at packages/effects/src/mirror/mirror-runtime.ts:29

	vao: WebGLVertexArrayObject;
	vbo: WebGLBuffer;
	textureSource: WebGLTexture;
	uniforms: {
		uSource: WebGLUniformLocation | null;
		uPosition: WebGLUniformLocation | null;
		uDirection: WebGLUniformLocation | null;
		uInvert: WebGLUniformLocation | null;
	};
};

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(`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. Ensure the render environment supports WebGL2 — for headless Chrome pass flags like --enable-webgl and --use-gl=angle or --use-gl=swiftshader.
  2. Reduce the number of concurrent WebGL-based effects in a single render.
  3. Update GPU drivers or switch to a software renderer (SwiftShader) in environments without a physical GPU.
  4. If context loss is the cause, retry the render after the browser re-acquires the context.
Defensive patterns

Strategy: fallback

Validate before calling

// Check WebGL2 shader allocation capability before using the effect
const testCanvas = document.createElement('canvas');
const testGl = testCanvas.getContext('webgl2');
if (testGl) {
  const testShader = testGl.createShader(testGl.VERTEX_SHADER);
  if (!testShader) {
    console.warn('WebGL2 shader allocation failed — mirror effect may not work');
  }
  testGl.deleteShader(testShader);
}

Try / catch

// Wrap effect usage in try-catch with a non-WebGL fallback
try {
  // apply mirror effect
} catch (e) {
  if (e instanceof Error && e.message.includes('WebGL shader')) {
    console.warn('WebGL unavailable, skipping mirror effect');
    // fall back to rendering without the effect
  } else {
    throw e;
  }
}

Prevention

When it happens

Trigger: The mirror effect's setupMirror runs during rendering; gl.createShader(type) returns null. This happens after the WebGL2 context is acquired but before any shader source is uploaded, indicating the context cannot allocate shader objects.

Common situations: CI/headless rendering with software rasterizers or missing GPU flags; too many simultaneous WebGL contexts exhausting driver limits; browser tab crash triggering context loss; VMs or Docker containers without GPU passthrough; corrupted or blacklisted GPU drivers.

Related errors


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