remotion-dev/remotion · error · Error

Failed to create WebGL shader

Error message

Failed to create WebGL shader

What it means

Thrown by compileShader in pixelate.ts when gl.createShader() returns null. The shader object is the first thing needed to compile GLSL, and a null return means the GL implementation cannot allocate another shader — almost always because the context is lost or has hit an internal shader-object cap. The guard prevents shaderSource/compileShader from receiving null.

Source

Thrown at packages/effects/src/pixelate.ts:87

uniform sampler2D uSource;
uniform float uBlockSize;
uniform vec2 uResolution;

void main() {
    vec2 pixelSizeUv = vec2(uBlockSize) / uResolution;
    vec2 blockUv = floor(vUv / pixelSizeUv) * pixelSizeUv + pixelSizeUv * 0.5;
    fragColor = texture(uSource, blockUv);
}
`;

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(`Pixelate 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. Confirm WebGL2 is functional with a probe: `const gl=canvas.getContext('webgl2'); const s=gl && gl.createShader(gl.VERTEX_SHADER);` — if s is null, the environment is the cause.
  2. On Remotion Lambda use the published Chrome layer with SwiftShader enabled; do not run with --disable-gpu without --use-gl=swiftshader.
  3. Reduce the number of distinct WebGL2 effects mounted concurrently; each pixelate instance compiles two shaders.
  4. Listen for 'webglcontextlost' on the canvas and remount the effect when 'webglcontextrestored' fires.
  5. Update the GPU driver if reproducing on a single physical machine.

Example fix

// before
import {pixelate} from '@remotion/effects';
const effect = pixelate();

// after — detect before mounting
function webgl2CanCompileShader(): boolean {
  const c = document.createElement('canvas');
  const gl = c.getContext('webgl2');
  if (!gl) return false;
  const s = gl.createShader(gl.VERTEX_SHADER);
  if (s) gl.deleteShader(s);
  return s !== null;
}
Defensive patterns

Strategy: try-catch

Validate before calling

function glCanCreateShader(gl: WebGL2RenderingContext): boolean {
  if (gl.isContextLost()) return false;
  const s = gl.createShader(gl.VERTEX_SHADER);
  if (s) gl.deleteShader(s);
  return s !== null;
}

Try / catch

try {
  pixelate();
} catch (err) {
  if (/Failed to create WebGL shader/.test((err as Error).message)) {
    // report WebGL2 unavailable; fall back to a non-GPU effect
  }
  throw err;
}

Prevention

When it happens

Trigger: pixelate() setup calls compileShader for the vertex shader (or fragment shader); gl.createShader(type) returns null. No GLSL has been compiled yet at this point, so the failure is purely about GL object allocation, not source correctness.

Common situations: Headless Chrome without GPU (SwiftShader); context lost between frames; many WebGL2 effects each allocating their own shaders in one tab; driver that caps total shader objects; environment that returned a WebGL2 context object but cannot actually service it (some virtualized GPU setups).

Related errors


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