remotion-dev/remotion · critical · Error

Failed to create WebGL shader

Error message

Failed to create WebGL shader

What it means

Thrown from linearGradientTint's WebGL2 setup when `gl.createShader(type)` returns null. Identical mechanism to other effects: the spec only returns null on context loss, OUT_OF_MEMORY, or handle exhaustion — the shader source has not been supplied yet.

Source

Thrown at packages/effects/src/linear-gradient-tint.ts:211

	}

	vec2 publicUv = vec2(vUv.x, 1.0 - vUv.y);
	vec4 tintColor = mix(uStartColor, uEndColor, gradientProgress(publicUv));
	vec3 sourceRgb = texColor.rgb / alpha;
	vec3 blended = mix(sourceRgb, tintColor.rgb, uAmount * tintColor.a);

	fragColor = vec4(blended * alpha, alpha);
}
`;

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

	return shader;
};

const createProgram = (gl: WebGL2RenderingContext): WebGLProgram => {
	const vs = compileShader(gl, gl.VERTEX_SHADER, VERTEX_SHADER);
	const fs = compileShader(gl, gl.FRAGMENT_SHADER, FRAGMENT_SHADER);

View on GitHub (pinned to 78fe4bb3fd)

Solutions

  1. Cache the setup keyed by params and always call the matching cleanup.
  2. Handle `webglcontextlost` and rebuild on restore.
  3. Reduce concurrently active WebGL effects per canvas.
  4. Use GPU-enabled render workers and avoid disabling GPU in headless Chrome.
Defensive patterns

Strategy: fallback

Validate before calling

const webgl2Available = (canvas: HTMLCanvasElement): boolean => {
  try { return !!canvas.getContext('webgl2'); } catch { return false; }
};

Type guard

const supportsWebGL2 = (): boolean => {
  try { return !!document.createElement('canvas').getContext('webgl2'); } catch { return false; }
};

Try / catch

let state = null;
try { state = setupLinearGradientTint(canvas); } catch (err) {
  console.error('linearGradientTint unavailable', err);
}

Prevention

When it happens

Trigger: Allocating many WebGL effects until shader-handle exhaustion; setup on a lost context; headless/Chromium-for-Testing refusing object creation under memory pressure.

Common situations: Stacking many effects per frame on Lambda; `--disable-gpu` headless runs; context loss mid-setup; leaking setups without cleanup.

Related errors


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