remotion-dev/remotion · error · Error

Failed to create WebGL program

Error message

Failed to create WebGL program

What it means

Thrown by linkProgram in pixelate.ts when gl.createProgram() returns null. A program object is the container that links vertex+fragment shaders; a null return means the GL implementation cannot allocate the program — almost always because the context is lost or exhausted. The guard prevents attachShader/linkProgram from receiving null.

Source

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

	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 => {
	const program = gl.createProgram();
	if (!program) {
		throw new Error('Failed to create WebGL program');
	}

	gl.attachShader(program, vs);
	gl.attachShader(program, fs);
	gl.linkProgram(program);
	if (!gl.getProgramParameter(program, gl.LINK_STATUS)) {
		const log = gl.getProgramInfoLog(program);
		gl.deleteProgram(program);
		throw new Error(`Pixelate program link failed: ${log ?? '(no log)'}`);
	}

	return program;
};

const createPixelateState = (gl: WebGL2RenderingContext): PixelateState => {
	const vs = compileShader(gl, gl.VERTEX_SHADER, VERTEX_SHADER);
	const fs = compileShader(gl, gl.FRAGMENT_SHADER, FRAGMENT_SHADER);
	const program = linkProgram(gl, vs, fs);

View on GitHub (pinned to 78fe4bb3fd)

Solutions

  1. Check `gl.isContextLost()` before mounting and remount the effect on restore.
  2. Reduce concurrent WebGL2 effects — each pixelate holds one compiled program for its lifetime.
  3. On Lambda, use the correct Chrome for Testing layer and adequate function memory.
  4. Reproduce with stable desktop Chrome to confirm the environment is at fault.
  5. Free other GPU resources before applying pixelate.

Example fix

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

// after — confirm program allocation is possible
function glCanCreateProgram(gl: WebGL2RenderingContext): boolean {
  if (gl.isContextLost()) return false;
  const p = gl.createProgram();
  const ok = p !== null;
  if (p) gl.deleteProgram(p);
  return ok;
}
Defensive patterns

Strategy: try-catch

Validate before calling

function glCanCreateProgram(gl: WebGL2RenderingContext): boolean {
  if (gl.isContextLost()) return false;
  const p = gl.createProgram();
  if (p) gl.deleteProgram(p);
  return p !== null;
}

Try / catch

try {
  pixelate();
} catch (err) {
  if (/Failed to create WebGL program/.test((err as Error).message)) {
    // free GPU resources or remount on context restore
  }
  throw err;
}

Prevention

When it happens

Trigger: pixelate setup calls linkProgram after both shaders compiled successfully; gl.createProgram() returns null. Because shaders succeeded, the cause is GL object allocation, not source correctness.

Common situations: Context lost between the shader compiles and the program creation; many effects holding live programs in one tab; SwiftShader under load on Lambda; a virtualized GPU with a low program-object cap.

Related errors


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