remotion-dev/remotion · error · Error

Failed to create shader

Error message

Failed to create shader

What it means

Thrown by the tv-signal-off effect's internal compileShader helper when gl.createShader() returns null during effect setup. A null return from createShader means the WebGL2 context is lost, the GPU is out of memory, or the context was never validly initialized. The library fails fast rather than passing a null shader to subsequent GL calls, which would only produce a more confusing downstream error.

Source

Thrown at packages/effects/src/tv-signal-off.ts:134

void main() {
	vec4 color = texture(uSource, vUv);
	vec3 sourceColor = color.a == 0.0 ? vec3(0.0) : color.rgb / color.a;
	vec3 bars = tvPattern(vUv);
	vec3 mixed = mix(sourceColor, bars, uAmount);

	fragColor = vec4(mixed * color.a, color.a);
}
`;

const compileShader = (
	gl: WebGL2RenderingContext,
	type: number,
	source: string,
): WebGLShader => {
	const shader = gl.createShader(type);
	if (!shader) {
		throw new Error('Failed to create shader');
	}

	gl.shaderSource(shader, source);
	gl.compileShader(shader);

	if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
		const info = gl.getShaderInfoLog(shader) ?? 'Unknown shader compile error';
		gl.deleteShader(shader);
		throw new Error(info);
	}

	return shader;
};

const createProgram = (
	gl: WebGL2RenderingContext,
	vertexSource: string,
	fragmentSource: string,

View on GitHub (pinned to 78fe4bb3fd)

Solutions

  1. Reduce the number of concurrent render processes / parallelism so fewer simultaneous WebGL2 contexts are alive
  2. Ensure the headless browser has hardware GPU acceleration enabled (pass --use-gl=angle or the appropriate Chrome flags for your environment)
  3. Listen for the webglcontextlost event on the canvas and retry the render or effect setup after webglcontextrestored fires
  4. Update or replace GPU drivers; if using a VM, switch to one with GPU passthrough or a dedicated render GPU

Example fix

// before: many parallel renders exhaust GPU contexts
const {combineVideos} = await renderMedia({serveUrl, codec: 'h264', concurrency: 16});

// after: lower concurrency to reduce simultaneous GL contexts
await renderMedia({serveUrl, codec: 'h264', concurrency: 4});
Defensive patterns

Strategy: try-catch

Try / catch

try {
  const state = setupTvSignalOffEffect(canvas);
} catch (err) {
  if (err instanceof Error && err.message === 'Failed to create shader') {
    // Context is lost or GPU resources exhausted — retry the whole render
    // after a context restoration event or process restart.
    throw new Error('WebGL2 context lost during tv-signal-off setup. Retry the render.');
  }
  throw err;
}

Prevention

When it happens

Trigger: The tvSignalOff effect's setup() calls createTvSignalOffState -> createProgram -> compileShader, and gl.createShader(gl.VERTEX_SHADER or gl.FRAGMENT_SHADER) returns null. This occurs when the WebGL2 context was acquired but is now in a WEBGL_lose_context lost state, or when the process has exhausted its GPU object allocation budget.

Common situations: Headless Chrome (Lambda, CI, Docker) with software rendering (SwiftShader) under memory pressure; too many concurrent Remotion render processes each holding their own GL context; a browser tab whose GL context was lost after a GPU driver crash or TDR; rendering on a machine where the GPU driver has crashed mid-render.

Related errors


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