remotion-dev/remotion · error · Error

Failed to create WebGL buffer

Error message

Failed to create WebGL buffer

What it means

Thrown by pixelDissolve's createFullscreenQuad when gl.createBuffer() returns null after the VAO was already allocated and bound. WebGL2 returns null on buffer allocation when the context is lost or GPU memory for vertex buffers is exhausted. The null-check aborts before bindBuffer/bufferData would silently no-op.

Source

Thrown at packages/effects/src/pixel-dissolve.ts:254

	return program;
};

const createFullscreenQuad = (
	gl: WebGL2RenderingContext,
): {
	readonly vao: WebGLVertexArrayObject;
	readonly vbo: WebGLBuffer;
} => {
	const vao = gl.createVertexArray();
	if (!vao) {
		throw new Error('Failed to create WebGL vertex array');
	}

	gl.bindVertexArray(vao);

	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,
		new Float32Array([-1, -1, 0, 0, 1, -1, 1, 0, -1, 1, 0, 1, 1, 1, 1, 1]),
		gl.STATIC_DRAW,
	);

	return {vao, vbo};
};

export const pixelDissolve = createEffect<
	PixelDissolveParams,
	PixelDissolveState
>({
	type: 'dev.remotion.effects.pixelDissolve',
	label: 'pixelDissolve()',

View on GitHub (pinned to 78fe4bb3fd)

Solutions

  1. Free other GPU resources before mounting pixelDissolve — unload unused video/image sources and other WebGL effects first.
  2. Check that the context is not lost: `const ext = gl.getExtension('WEBGL_lose_context'); gl.isContextLost()` and remount if true.
  3. On Lambda, use a larger memory function (3008 MB+) so Chrome has more headroom for GPU buffers.
  4. Reduce concurrent pixelDissolve instances to one per composition pass.
  5. If reproducible only on a specific machine, update or roll back the GPU driver.

Example fix

// before
import {pixelDissolve} from '@remotion/effects';
const effect = pixelDissolve();

// after — verify the live context can allocate before relying on the effect
function glCanAllocateBuffer(gl: WebGL2RenderingContext): boolean {
  if (gl.isContextLost()) return false;
  const probe = gl.createBuffer();
  const ok = probe !== null;
  if (probe) gl.deleteBuffer(probe);
  return ok;
}
Defensive patterns

Strategy: try-catch

Validate before calling

function glCanCreateBuffer(gl: WebGL2RenderingContext): boolean {
  if (gl.isContextLost()) return false;
  const b = gl.createBuffer();
  if (b) gl.deleteBuffer(b);
  return b !== null;
}

Try / catch

try {
  pixelDissolve();
} catch (err) {
  if (/Failed to create WebGL buffer/.test((err as Error).message)) {
    // free other GPU resources and retry, or fall back to a non-WebGL effect
  }
  throw err;
}

Prevention

When it happens

Trigger: pixelDissolve setup reaches createBuffer() (VAO succeeded) but the GL implementation refuses to allocate a new ARRAY_BUFFER. This is the second allocation in createFullscreenQuad, so it implies the context was healthy enough to make a VAO but degraded by the time a buffer was requested.

Common situations: GPU memory pressure from many simultaneously loaded video textures; context loss arriving between the VAO and buffer calls; SwiftShader under memory pressure in Lambda; a buggy driver that caps buffer count below the VAO count.

Related errors


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