remotion-dev/remotion · error · Error

Failed to create WebGL shader

Error message

Failed to create WebGL shader

What it means

Thrown by compileShader() in the linear-progressive-blur runtime when gl.createShader() returns null. The WebGL2 context exists but refused to allocate a shader object, so the two-pass blur (horizontal+vertical) cannot be built. Same failure class as the linear-gradient shader allocation, specific to this effect's runtime.

Source

Thrown at packages/effects/src/linear-progressive-blur/linear-progressive-blur-runtime.ts:39

	readonly programHorizontal: WebGLProgram;
	readonly programVertical: WebGLProgram;
	readonly vao: WebGLVertexArrayObject;
	readonly vbo: WebGLBuffer;
	readonly textureSource: WebGLTexture;
	readonly textureIntermediate: WebGLTexture;
	readonly framebuffer: WebGLFramebuffer;
	readonly horizontal: LinearProgressiveBlurUniforms;
	readonly vertical: LinearProgressiveBlurUniforms;
};

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

	return shader;
};

const linkProgram = (
	gl: WebGL2RenderingContext,
	vs: WebGLShader,

View on GitHub (pinned to 78fe4bb3fd)

Solutions

  1. Retry the render once after restarting Chrome/the worker — usually transient.
  2. Force a software GL backend: `--gl=angle --angle-backend=swiftshader`.
  3. Lower `--concurrency` / framesPerLambda to reduce simultaneous contexts.
  4. Update Chrome and GPU drivers on the host.
  5. Inspect Chrome logs for GPU-process crashes ('ContextResult::kTransientFailure').

Example fix

// before — default GL fails on a GPU-less or saturated host
//   npx remotion render MyComp out.mp4

// after
//   npx remotion render MyComp out.mp4 --gl=angle --angle-backend=swiftshader
Defensive patterns

Strategy: retry

Validate before calling

function supportsWebGL2ShaderAlloc(canvas: HTMLCanvasElement): boolean {
  const gl = canvas.getContext('webgl2');
  if (!gl) return false;
  const probe = gl.createShader(gl.VERTEX_SHADER);
  const ok = probe !== null;
  if (probe) gl.deleteShader(probe);
  return ok;
}

Try / catch

try {
  renderWithLinearProgressiveBlur();
} catch (err) {
  if (err instanceof Error && err.message === 'Failed to create WebGL shader') {
    await restartRendererWorker();
    renderWithLinearProgressiveBlur();
  } else throw err;
}

Prevention

When it happens

Trigger: Mounting linearProgressiveBlur during render/preview when the WebGL2 context is lost, GPU memory is exhausted, or the browser's active-context limit is exceeded. The runtime builds two programs (horizontal, vertical), so it stresses shader allocation twice.

Common situations: Concurrent Remotion Lambda/local renders saturating GPU objects; headless Chrome without a working GL backend; a crashed Chrome GPU process leaving the context failing; long Studio sessions with many effects mounted.

Related errors


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