remotion-dev/remotion · error · Error

Failed to create exposure shader program

Error message

Failed to create exposure shader program

What it means

Thrown inside createProgram() in exposure.ts when gl.createProgram() returns null (exposure.ts:133-135). A null program object means the GL driver declined to allocate a program handle — typically a lost context or an exhausted program-object pool. The two shaders have already compiled successfully, but there is no program to link them into.

Source

Thrown at packages/effects/src/exposure.ts:134

	}

	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(`Exposure shader compile failed: ${log ?? '(no log)'}`);
	}

	return shader;
};

const createProgram = (gl: WebGL2RenderingContext): WebGLProgram => {
	const vertexShader = compileShader(gl, gl.VERTEX_SHADER, VERTEX_SHADER);
	const fragmentShader = compileShader(gl, gl.FRAGMENT_SHADER, FRAGMENT_SHADER);
	const program = gl.createProgram();
	if (!program) {
		throw new Error('Failed to create exposure shader program');
	}

	gl.attachShader(program, vertexShader);
	gl.attachShader(program, fragmentShader);
	gl.linkProgram(program);
	gl.deleteShader(vertexShader);
	gl.deleteShader(fragmentShader);

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

	return program;
};

const createTexture = (gl: WebGL2RenderingContext): WebGLTexture => {

View on GitHub (pinned to 78fe4bb3fd)

Solutions

  1. Render with the Angle backend (--gl=angle / chromiumOptions.gl='angle' / Angle in Studio).
  2. Guarantee effect cleanup() runs so gl.deleteProgram frees handles; do not retain old exposure states.
  3. Reduce simultaneous WebGL2 effects and reuse identical exposure() params (calculateKey caching).
  4. Verify gl.isContextLost() is false before setup and restore the context otherwise.
  5. Move rendering to a host with adequate GL resources or update drivers.

Example fix

// before
const program = gl.createProgram();
if (!program) {
  throw new Error('Failed to create exposure shader program');
}

// after (caller guard before applying the effect)
if (gl.isContextLost()) {
  throw new Error('exposure setup aborted: WebGL2 context lost');
}
Defensive patterns

Strategy: try-catch

Validate before calling

const canAllocateProgram = (gl: WebGL2RenderingContext): boolean => {
  if (gl.isContextLost()) return false;
  const probe = gl.createProgram();
  if (!probe) return false;
  gl.deleteProgram(probe);
  return true;
};

Try / catch

try {
  // apply exposure(); for a custom canvas: const state = setupExposure(canvas);
} catch (err) {
  if (err instanceof Error && err.message === 'Failed to create exposure shader program') {
    // free other effects, restore context, retry on Angle
    throw err;
  }
  throw err;
}

Prevention

When it happens

Trigger: setupExposure() reaches createProgram() after both VERTEX_SHADER and FRAGMENT_SHADER compiled, but gl.createProgram() returns null. This happens when the context is lost or the driver's program-object limit is hit from leaked/un-cleaned effect programs.

Common situations: Long-running Studio leaking programs (cleanup() not called, so gl.deleteProgram never runs); compositions with many simultaneous exposure() instances; CI on a host whose GPU process crashed; software GL backends with low program-object ceilings.

Related errors


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