remotion-dev/remotion · critical · Error

Failed to create WebGL shader

Error message

Failed to create WebGL shader

What it means

Thrown by compileShader() inside the waves effect when gl.createShader(type) returns null. WebGL's createShader returns null on context loss, context destruction, or resource exhaustion. The shader type (vertex or fragment) is passed through from the caller. This prevents the waves effect from building its GLSL program.

Source

Thrown at packages/effects/src/waves.ts:367

		);
		return;
	}

	fragColor = vec4(
		premultipliedLine + texColor.rgb * (1.0 - lineAlpha),
		lineAlpha + texColor.a * (1.0 - lineAlpha)
	);
}
`;

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(`Waves 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. Handle 'webglcontextlost'/'webglcontextrestored' events and re-run setupWaves on a fresh canvas.
  2. Ensure cleanup of old effect states (the waves effect cleanup deletes programs but shaders are deleted inline — verify no leaks in custom wrappers).
  3. Reduce concurrent effect instances to lower shader object pressure.
  4. Update GPU drivers or switch render backends (hardware vs SwiftShader).
Defensive patterns

Strategy: try-catch

Try / catch

const gl = canvas.getContext('webgl2');
if (!gl || gl.isContextLost()) {
  return;
}
try {
  const state = setupWaves(canvas);
} catch (e) {
  if ((e as Error).message === 'Failed to create WebGL shader') {
    console.warn('Waves shader allocation failed:', (e as Error).message);
  }
}

Prevention

When it happens

Trigger: Called transitively from setupWaves() at packages/effects/src/waves.ts:446 via createProgram(gl, WAVES_VS, WAVES_FS) which calls compileShader for both vertex and fragment shaders. Fires when the GL context is lost or GPU shader object slots are exhausted. The shader source (WAVES_VS/WAVES_FS) is a static library constant, so user params do not cause this.

Common situations: WebGL context loss event during effect setup; long-running render with many effect instances leaking shader objects; constrained GPU environment (mobile, VM, older drivers); GPU process crash mid-setup.

Related errors


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