{"record":{"id":"7472c68ccfe9f7c1","repo":"remotion-dev/remotion","slug":"failed-to-create-shadows-and-highlights-vertex-buf","errorCode":null,"errorMessage":"Failed to create shadows and highlights vertex buffer","messagePattern":"Failed to create shadows and highlights vertex buffer","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/effects/src/shadows-highlights.ts","lineNumber":211,"sourceCode":"\t\tpremultipliedAlpha: true,\n\t\talpha: true,\n\t\tpreserveDrawingBuffer: true,\n\t});\n\tif (!gl) {\n\t\tthrow createWebGL2ContextError('shadows and highlights effect');\n\t}\n\n\tgl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, true);\n\n\tconst program = createProgram(gl);\n\tconst vao = gl.createVertexArray();\n\tif (!vao) {\n\t\tthrow new Error('Failed to create shadows and highlights vertex array');\n\t}\n\n\tconst vbo = gl.createBuffer();\n\tif (!vbo) {\n\t\tthrow new Error('Failed to create shadows and highlights vertex buffer');\n\t}\n\n\tgl.bindVertexArray(vao);\n\tgl.bindBuffer(gl.ARRAY_BUFFER, vbo);\n\tgl.bufferData(\n\t\tgl.ARRAY_BUFFER,\n\t\tnew Float32Array([-1, -1, 0, 0, 1, -1, 1, 0, -1, 1, 0, 1, 1, 1, 1, 1]),\n\t\tgl.STATIC_DRAW,\n\t);\n\n\tconst aPos = gl.getAttribLocation(program, 'aPos');\n\tconst aUv = gl.getAttribLocation(program, 'aUv');\n\tgl.enableVertexAttribArray(aPos);\n\tgl.vertexAttribPointer(aPos, 2, gl.FLOAT, false, 16, 0);\n\tgl.enableVertexAttribArray(aUv);\n\tgl.vertexAttribPointer(aUv, 2, gl.FLOAT, false, 16, 8);\n\tgl.bindVertexArray(null);\n","sourceCodeStart":193,"sourceCodeEnd":229,"githubUrl":"https://github.com/remotion-dev/remotion/blob/78fe4bb3fdb5a2cd68724393d63cb223db333fa7/packages/effects/src/shadows-highlights.ts#L193-L229","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Verify GPU acceleration is active in your render environment (headless Chrome flags, Lambda layer, or runner capabilities).","Ensure every effect instance is properly cleaned up — Remotion calls the effect's cleanup() to release GPU resources; avoid unmounted compositions that retain contexts.","Lower concurrency or parallelism so fewer WebGL2 contexts exist at once.","Update GPU drivers or switch to a host/runner that provides hardware-accelerated WebGL2."],"exampleFix":"// before — too many concurrent renders exhaust GPU buffers\nrenderMedia({ composition, concurrency: 16, ... });\n\n// after — reduce concurrency so each context can allocate\nrenderMedia({ composition, concurrency: 2, ... });","handlingStrategy":"try-catch","validationCode":"// Probe whether buffer allocation works on the current WebGL2 context\nfunction canAllocateBuffer(canvas: HTMLCanvasElement): boolean {\n  const gl = canvas.getContext('webgl2');\n  if (!gl) return false;\n  const buf = gl.createBuffer();\n  const ok = buf !== null;\n  if (buf) gl.deleteBuffer(buf);\n  return ok;\n}","typeGuard":"null","tryCatchPattern":"try {\n  shadowsHighlights({ highlights: 0.3 });\n} catch (e) {\n  if (e instanceof Error && e.message.includes('vertex buffer')) {\n    console.warn('WebGL2 buffer allocation failed, skipping effect');\n  } else {\n    throw e;\n  }\n}","preventionTips":["Reduce render concurrency to limit simultaneous GPU buffer allocations.","Ensure effect cleanup() runs to release buffers between renders.","Use a render environment with adequate GPU memory.","Monitor for context-loss events that invalidate allocated resources."],"tags":["webgl2","gpu","resource-allocation","memory","headless"],"backgroundTag":null,"analyzedSha":"78fe4bb3fdb5a2cd68724393d63cb223db333fa7","analyzedAt":"2026-08-12T17:18:50.444Z","schemaVersion":2},"datasetVersion":"2026-08-12T18:17:37.767Z"}