{"record":{"id":"efc0e245c16296f1","repo":"remotion-dev/remotion","slug":"failed-to-create-webgl-buffer-efc0e2","errorCode":null,"errorMessage":"Failed to create WebGL buffer","messagePattern":"Failed to create WebGL buffer","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/effects/src/zigzag.ts","lineNumber":443,"sourceCode":"\n\tgl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, true);\n\n\tconst program = createProgram(gl, ZIGZAG_VS, ZIGZAG_FS);\n\n\tconst vao = gl.createVertexArray();\n\tif (!vao) {\n\t\tthrow new Error('Failed to create WebGL vertex array');\n\t}\n\n\tgl.bindVertexArray(vao);\n\n\tconst data = new Float32Array([\n\t\t-1, -1, 0, 0, 1, -1, 1, 0, -1, 1, 0, 1, 1, 1, 1, 1,\n\t]);\n\n\tconst vbo = gl.createBuffer();\n\tif (!vbo) {\n\t\tthrow new Error('Failed to create WebGL buffer');\n\t}\n\n\tgl.bindBuffer(gl.ARRAY_BUFFER, vbo);\n\tgl.bufferData(gl.ARRAY_BUFFER, data, gl.STATIC_DRAW);\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\n\tgl.bindVertexArray(null);\n\n\tconst colorCanvas = document.createElement('canvas');\n\tcolorCanvas.width = 1;\n\tcolorCanvas.height = 1;\n\tconst colorCtx = colorCanvas.getContext('2d', {willReadFrequently: true});","sourceCodeStart":425,"sourceCodeEnd":461,"githubUrl":"https://github.com/remotion-dev/remotion/blob/78fe4bb3fdb5a2cd68724393d63cb223db333fa7/packages/effects/src/zigzag.ts#L425-L461","documentation":"Zigzag setup allocates a vertex buffer (gl.createBuffer) to upload the fullscreen-quad vertices; a null return means the GL context refused another buffer object, so the effect throws before configuring attributes. Like the other null-resource throws, it reflects a lost/limited GL context rather than any parameter.","triggerScenarios":"setupZigzag calls gl.createBuffer() and receives null on the first zigzag frame.","commonSituations":"Headless render farm without working GPU acceleration; long-running session leaking GL objects; many effects each holding their own context; VM/Remote-Desktop GPU forwarding dropping buffer allocation.","solutions":["Ensure the render browser exposes a working WebGL2 context that is not lost.","Render with Remotion's bundled Chromium (CLI/Lambda) with the software GPU path enabled.","Reduce concurrent WebGL contexts by rendering effects in fewer parallel compositions.","Recover from webglcontextlost by unmounting and re-mounting the composition.","Update GPU drivers / backend where allocation fails."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"const gl = document.createElement('canvas').getContext('webgl2');\nconst webglOk = gl != null && gl.createBuffer() != null && !gl.isContextLost();","typeGuard":"const canAllocateBuffer = (): boolean => {\n  const gl = document.createElement('canvas').getContext('webgl2');\n  return gl != null && !gl.isContextLost() && gl.createBuffer() != null;\n};","tryCatchPattern":"try {\n  return <VideoEffects effects={[zigzag({colors: ['#ff0000', '#00ff00']})]} />;\n} catch (err) {\n  if (err instanceof Error && err.message === 'Failed to create WebGL buffer') {\n    return <Video />;\n  }\n  throw err;\n}","preventionTips":["Probe buffer allocation before mounting zigzag().","Render with Remotion's bundled Chromium; do not disable the software GPU.","Reduce concurrent WebGL effects to free buffer slots.","Re-mount on webglcontextlost."],"tags":["webgl","gpu","rendering","headless","context-loss"],"backgroundTag":null,"analyzedSha":"78fe4bb3fdb5a2cd68724393d63cb223db333fa7","analyzedAt":"2026-08-12T17:18:50.444Z","schemaVersion":2},"datasetVersion":"2026-08-12T18:17:37.767Z"}