remotion-dev/remotion · error · Error

Failed to create exposure vertex array

Error message

Failed to create exposure vertex array

What it means

Thrown during setupExposure() when gl.createVertexArray() returns null (exposure.ts:181-183). A null VAO means the driver refused another vertex-array object — context lost or the driver's VAO ceiling reached. Without a VAO the exposure fullscreen-quad attribute state cannot be captured, so setup fails.

Source

Thrown at packages/effects/src/exposure.ts:182

	return texture;
};

const setupExposure = (target: HTMLCanvasElement): ExposureState => {
	const gl = target.getContext('webgl2', {
		premultipliedAlpha: true,
		alpha: true,
		preserveDrawingBuffer: true,
	});
	if (!gl) {
		throw createWebGL2ContextError('exposure 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 exposure vertex array');
	}

	const vbo = gl.createBuffer();
	if (!vbo) {
		throw new Error('Failed to create exposure 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);

View on GitHub (pinned to 78fe4bb3fd)

Solutions

  1. Render with the Angle backend (--gl=angle / chromiumOptions.gl='angle') which exposes higher, consistent VAO limits.
  2. Reduce concurrent WebGL2 effects in the composition and reuse identical exposure() params (calculateKey caching).
  3. Verify gl.isContextLost() is false and restore the context if needed.
  4. Ensure effect cleanup() runs (it calls gl.deleteVertexArray) so VAOs are recycled.
  5. Update GPU drivers; older drivers leak VAOs across resets.

Example fix

// before
const vao = gl.createVertexArray();
if (!vao) {
  throw new Error('Failed to create exposure vertex array');
}

// after (composition-level reuse)
// share one exposure({stops: x}) across layers instead of one per layer
// so calculateKey collapses them onto a single canvas/VAO.
Defensive patterns

Strategy: try-catch

Validate before calling

const canAllocateVao = (gl: WebGL2RenderingContext): boolean => {
  if (gl.isContextLost()) return false;
  const probe = gl.createVertexArray();
  if (!probe) return false;
  gl.deleteVertexArray(probe);
  return true;
};

Try / catch

try {
  // apply exposure(); for a custom canvas: const state = setupExposure(canvas);
} catch (err) {
  if (err instanceof Error && err.message === 'Failed to create exposure vertex array') {
    // reduce concurrent WebGL2 effects, retry on Angle
    throw err;
  }
  throw err;
}

Prevention

When it happens

Trigger: setupExposure() runs createProgram() successfully, then gl.createVertexArray() returns null. This happens on a lost context or when the driver's implementation-defined VAO limit is exhausted by many simultaneous WebGL2 effects.

Common situations: Compositions stacking numerous WebGL2 effects (each holds a VAO) on a driver with a low VAO cap; GPU process crash leaving the context lost; CI software-GL backends with tight VAO limits.

Related errors


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