remotion-dev/remotion · critical · Error

Failed to create WebGL shader

Error message

Failed to create WebGL shader

What it means

Thrown by compileShader in flannel when gl.createShader() returns null. WebGL2 returns null from createShader only when the context is lost, the type is invalid, or the implementation has run out of GPU resources. This is a GPU/driver-level failure, not a shader source problem (source errors surface as 605).

Source

Thrown at packages/effects/src/flannel.ts:194

	vec3 sourceRgb = source.rgb / source.a;
	float luminance = dot(sourceRgb, vec3(0.2126, 0.7152, 0.0722));
	vec3 plaidColor = mix(uBaseColor.rgb, uStripeColor.rgb, bands * uStripeColor.a);
	plaidColor = mix(plaidColor, uStripeColor.rgb * 0.72, crossing * uStripeColor.a);
	plaidColor *= mix(0.58, 1.18, luminance) + weave;
	vec3 result = mix(sourceRgb, clamp(plaidColor, 0.0, 1.0), uAmount);

	fragColor = vec4(result * source.a, source.a);
}
`;

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

	return shader;
};

const setupFlannel = (target: HTMLCanvasElement): FlannelState => {
	const gl = target.getContext('webgl2', {
		premultipliedAlpha: true,
		alpha: true,
		preserveDrawingBuffer: true,

View on GitHub (pinned to 78fe4bb3fd)

Solutions

  1. Reduce the number of simultaneous WebGL effects on screen.
  2. Retry the render on a fresh Chrome instance or different worker.
  3. Update GPU drivers / use a Chromium build with working GL (Remotion's bundled Chrome).
Defensive patterns

Strategy: retry

Try / catch

let effect;
for (let attempt = 0; attempt < 3; attempt++) {
  try {
    effect = flannel(params);
    break;
  } catch (err) {
    if (attempt === 2 || !/WebGL|GPU/i.test(String(err))) throw err;
    await new Promise((r) => setTimeout(r, 200 * (attempt + 1)));
  }
}

Prevention

When it happens

Trigger: Calling flannel() when the WebGL2 context was just lost (tab backgrounded, GPU crash, too many contexts); hardware/driver that fails to allocate shader objects; running in a headless browser with software GL and exhausted resources.

Common situations: Rendering many concurrent flannel layers in Lambda/serverless where GPU memory is tight; testing in older virtualized GL implementations; switching tabs during render and resuming.

Related errors


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