remotion-dev/remotion · error · Error
Failed to create shadows and highlights vertex array
Error message
Failed to create shadows and highlights vertex array
What it means
The shadowsHighlights() effect calls gl.createVertexArray() during its setup phase and throws this Error when the WebGL2 context returns null. A null VAO means the GPU driver refused to allocate a vertex array object even though the context itself was successfully acquired. This is an environment-level failure, not a parameter validation error.
Source
Thrown at packages/effects/src/shadows-highlights.ts:206
const setupShadowsHighlights = (
target: HTMLCanvasElement,
): ShadowsHighlightsState => {
const gl = target.getContext('webgl2', {
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);View on GitHub (pinned to 78fe4bb3fd)
Solutions
- Ensure your render environment has GPU acceleration enabled — for headless Chrome pass flags like --use-gl=angle --use-angle=gl --enable-features=Vulkan or run on a runner with a discrete GPU.
- Reduce the number of distinct WebGL2-backed effects applied simultaneously; each shadowsHighlights() instance allocates its own context and resources.
- Check for WebGL2 context loss by listening to the 'webglcontextlost' event on the canvas before relying on the effect.
- If running in Lambda, verify the Chrome binary and layer include GPU-compatible libraries (libGL, libEGL, libGLESv2).
Example fix
// before — fails on a GPU-less CI runner
renderMedia({
composition,
serveUrl,
inputProps,
});
// after — enable GPU in the headless Chromium used by the renderer
// (set via puppeteerInstance or renderMedia chromiumOptions)
renderMedia({
composition,
serveUrl,
inputProps,
chromiumOptions: {
enableMultiProcessOnLinux: true,
// ensure the headless shell picks up system GL
},
});
// and launch Chrome with: --use-gl=angle --use-angle=gl Defensive patterns
Strategy: try-catch
Validate before calling
// Before applying shadowsHighlights, verify the canvas can get a WebGL2 context
function canAllocateWebGL2(canvas: HTMLCanvasElement): boolean {
const gl = canvas.getContext('webgl2', { alpha: true });
if (!gl) return false;
const testVao = gl.createVertexArray();
const ok = testVao !== null;
if (testVao) gl.deleteVertexArray(testVao);
// Note: getContext returns the same context on repeated calls; do not lose it
return ok;
} Type guard
null
Try / catch
try {
// Apply the effect in a composition
shadowsHighlights({ shadows: -0.5 });
} catch (e) {
if (e instanceof Error && e.message.includes('vertex array')) {
// WebGL2 resource allocation failed — fall back to no effect or a 2D-canvas approach
console.warn('WebGL2 VAO unavailable, skipping shadowsHighlights');
} else {
throw e;
}
} Prevention
- Ensure the render environment has GPU acceleration (headless Chrome flags, Lambda GPU layer).
- Limit the number of concurrent WebGL2-backed effects to avoid exhausting the VAO pool.
- Handle 'webglcontextlost' events and re-render after context restoration.
- Verify GPU drivers are up to date in CI and production environments.
When it happens
Trigger: Calling shadowsHighlights() in a composition that renders on a machine whose GPU or driver cannot service WebGL2 VAO allocation. Most commonly seen in headless Chromium without GPU passthrough, in CI runners with software rendering, or when too many simultaneous WebGL2 contexts have exhausted the driver's object pool.
Common situations: Running Remotion Lambda or Chrome Headless Shell in CI without --enable-features=Vulkan or proper GPU flags; rendering on a VM with no GPU; opening dozens of effects-heavy compositions in parallel tabs that each create their own WebGL2 context; a transient context-loss event immediately after getContext succeeded.
Related errors
- Failed to create shadows and highlights vertex buffer
- Failed to create WebGL shader
- Failed to create WebGL vertex array
- Failed to create WebGL shader
- Failed to create WebGL vertex array
AI-assisted analysis of remotion-dev/remotion@78fe4bb3fd (2026-08-12).
Data as JSON: /api/errors/4a80d72b6e60abdf.
Report an issue: GitHub.