remotion-dev/remotion · error · Error

Failed to create WebGL vertex array

Error message

Failed to create WebGL vertex array

What it means

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

Source

Thrown at packages/effects/src/fisheye/fisheye-runtime.ts:110

};

export const setupFisheye = (target: HTMLCanvasElement): FisheyeState => {
	const gl = target.getContext('webgl2', {
		premultipliedAlpha: true,
		alpha: true,
		preserveDrawingBuffer: true,
	});
	if (!gl) {
		throw createWebGL2ContextError('fisheye effect');
	}

	gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, true);

	const program = createProgram(gl, FISHEYE_VS, FISHEYE_FS);

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

	gl.bindVertexArray(vao);

	const data = new Float32Array([
		-1, -1, 0, 0, 1, -1, 1, 0, -1, 1, 0, 1, 1, 1, 1, 1,
	]);

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

	gl.bindBuffer(gl.ARRAY_BUFFER, vbo);
	gl.bufferData(gl.ARRAY_BUFFER, data, gl.STATIC_DRAW);

	gl.enableVertexAttribArray(0);
	gl.vertexAttribPointer(0, 2, gl.FLOAT, false, 16, 0);

View on GitHub (pinned to 78fe4bb3fd)

Solutions

  1. Render with the Angle backend (--gl=angle / chromiumOptions.gl='angle') for higher, consistent VAO limits.
  2. Reduce concurrent WebGL2 effects and reuse identical fisheye() params (calculateKey caching).
  3. If using the runtime directly, always call cleanupFisheye() so VAOs are recycled.
  4. Verify gl.isContextLost() is false and restore the context if needed.
  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 WebGL vertex array');
}

// after (cleanup discipline)
const state = setupFisheye(canvas);
try { /* applyFisheye(...) */ } finally { cleanupFisheye(state); }
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

import {setupFisheye, cleanupFisheye} from '@remotion/effects/fisheye-runtime';

let state;
try {
  state = setupFisheye(canvas);
} catch (err) {
  if (err instanceof Error && err.message === 'Failed to create WebGL vertex array') {
    // reduce concurrent WebGL2 effects, retry on Angle
    throw err;
  }
  throw err;
}
try { /* applyFisheye(state, ...) */ } finally { cleanupFisheye(state); }

Prevention

When it happens

Trigger: setupFisheye() 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 or leaked VAOs from un-cleaned fisheye states.

Common situations: Compositions stacking numerous WebGL2 effects (each holds a VAO) on a driver with a low VAO cap; apps using fisheye-runtime without cleanupFisheye() (which would gl.deleteVertexArray); 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/1f3f6f5e8e48e9c8. Report an issue: GitHub.