remotion-dev/remotion · error · Error

Failed to create shadows and highlights vertex buffer

Error message

Failed to create shadows and highlights vertex buffer

What it means

The shadowsHighlights() effect calls gl.createBuffer() during setup to allocate a vertex buffer object (VBO) for its fullscreen quad. When the WebGL2 driver returns null, the effect throws this Error. Like the VAO failure, this indicates the GPU cannot allocate a buffer even though the context was created successfully.

Source

Thrown at packages/effects/src/shadows-highlights.ts:211

		premultipliedAlpha: true,
		alpha: true,
		preserveDrawingBuffer: true,
	});
	if (!gl) {
		throw createWebGL2ContextError('shadows and highlights effect');
	}

	gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, true);

	const program = createProgram(gl);
	const vao = gl.createVertexArray();
	if (!vao) {
		throw new Error('Failed to create shadows and highlights vertex array');
	}

	const vbo = gl.createBuffer();
	if (!vbo) {
		throw new Error('Failed to create shadows and highlights vertex buffer');
	}

	gl.bindVertexArray(vao);
	gl.bindBuffer(gl.ARRAY_BUFFER, vbo);
	gl.bufferData(
		gl.ARRAY_BUFFER,
		new Float32Array([-1, -1, 0, 0, 1, -1, 1, 0, -1, 1, 0, 1, 1, 1, 1, 1]),
		gl.STATIC_DRAW,
	);

	const aPos = gl.getAttribLocation(program, 'aPos');
	const aUv = gl.getAttribLocation(program, 'aUv');
	gl.enableVertexAttribArray(aPos);
	gl.vertexAttribPointer(aPos, 2, gl.FLOAT, false, 16, 0);
	gl.enableVertexAttribArray(aUv);
	gl.vertexAttribPointer(aUv, 2, gl.FLOAT, false, 16, 8);
	gl.bindVertexArray(null);

View on GitHub (pinned to 78fe4bb3fd)

Solutions

  1. Verify GPU acceleration is active in your render environment (headless Chrome flags, Lambda layer, or runner capabilities).
  2. Ensure every effect instance is properly cleaned up — Remotion calls the effect's cleanup() to release GPU resources; avoid unmounted compositions that retain contexts.
  3. Lower concurrency or parallelism so fewer WebGL2 contexts exist at once.
  4. Update GPU drivers or switch to a host/runner that provides hardware-accelerated WebGL2.

Example fix

// before — too many concurrent renders exhaust GPU buffers
renderMedia({ composition, concurrency: 16, ... });

// after — reduce concurrency so each context can allocate
renderMedia({ composition, concurrency: 2, ... });
Defensive patterns

Strategy: try-catch

Validate before calling

// Probe whether buffer allocation works on the current WebGL2 context
function canAllocateBuffer(canvas: HTMLCanvasElement): boolean {
  const gl = canvas.getContext('webgl2');
  if (!gl) return false;
  const buf = gl.createBuffer();
  const ok = buf !== null;
  if (buf) gl.deleteBuffer(buf);
  return ok;
}

Type guard

null

Try / catch

try {
  shadowsHighlights({ highlights: 0.3 });
} catch (e) {
  if (e instanceof Error && e.message.includes('vertex buffer')) {
    console.warn('WebGL2 buffer allocation failed, skipping effect');
  } else {
    throw e;
  }
}

Prevention

When it happens

Trigger: Calling shadowsHighlights() when the WebGL2 context exists but GPU memory is exhausted or the driver is in a degraded state. Happens on systems with limited VRAM, in headless renderers relying on SwiftShader/software GL, or after a context-loss event that invalidated previously allocated resources.

Common situations: CI environments using software rendering (SwiftShader); Remotion Lambda with an outdated or misconfigured Chrome layer; rendering very large frame sizes that stress the software rasterizer; a page that leaked GPU resources from prior effects without calling cleanup.

Related errors


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