{"record":{"id":"b348b048cc5d37a8","repo":"remotion-dev/remotion","slug":"failed-to-create-webgl-texture-b348b0","errorCode":null,"errorMessage":"Failed to create WebGL texture","messagePattern":"Failed to create WebGL texture","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/effects/src/zigzag.ts","lineNumber":404,"sourceCode":"\tgl: WebGL2RenderingContext,\n\tvertexSource: string,\n\tfragmentSource: string,\n): WebGLProgram => {\n\tconst vs = compileShader(gl, gl.VERTEX_SHADER, vertexSource);\n\tconst fs = compileShader(gl, gl.FRAGMENT_SHADER, fragmentSource);\n\tconst program = linkProgram(gl, vs, fs);\n\tgl.deleteShader(vs);\n\tgl.deleteShader(fs);\n\treturn program;\n};\n\nconst createTexture = (\n\tgl: WebGL2RenderingContext,\n\tfilter: number,\n): WebGLTexture => {\n\tconst texture = gl.createTexture();\n\tif (!texture) {\n\t\tthrow new Error('Failed to create WebGL texture');\n\t}\n\n\tgl.bindTexture(gl.TEXTURE_2D, texture);\n\tgl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, filter);\n\tgl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, filter);\n\tgl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);\n\tgl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);\n\tgl.bindTexture(gl.TEXTURE_2D, null);\n\treturn texture;\n};\n\nconst setupZigzag = (target: HTMLCanvasElement): ZigzagState => {\n\tconst gl = target.getContext('webgl2', {\n\t\tpremultipliedAlpha: true,\n\t\talpha: true,\n\t\tpreserveDrawingBuffer: true,\n\t});\n\tif (!gl) {","sourceCodeStart":386,"sourceCodeEnd":422,"githubUrl":"https://github.com/remotion-dev/remotion/blob/78fe4bb3fdb5a2cd68724393d63cb223db333fa7/packages/effects/src/zigzag.ts#L386-L422","documentation":"Zigzag creates two GL textures — a LINEAR-filtered source sampler and a NEAREST-filtered palette sampler — via a shared createTexture helper; if the context returns null it throws 'Failed to create WebGL texture'. The effect samples both the video frame and the 1-D color palette, so it cannot draw without them. Null allocation means a lost/limited context, not a parameter error.","triggerScenarios":"setupZigzag calls createTexture(gl, gl.LINEAR) or createTexture(gl, gl.NEAREST) and gl.createTexture() returns null on the first frame.","commonSituations":"Headless/CI renderer with degraded WebGL2; context lost; too many textures alive across concurrent effects; software backend capping texture allocation.","solutions":["Confirm a healthy WebGL2 context (non-null getContext('webgl2'), isContextLost() false) before applying zigzag().","Render with Remotion's bundled Chromium with the software GPU enabled; avoid --disable-gpu.","Reduce concurrently-active WebGL effects to free texture-object slots.","Handle webglcontextlost by re-mounting the composition so setup reinitializes.","Update GPU drivers / move to a host with a conformant WebGL2 implementation."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"const gl = document.createElement('canvas').getContext('webgl2');\nconst webglOk = gl != null && gl.createTexture() != null && !gl.isContextLost();","typeGuard":"const canAllocateTexture = (): boolean => {\n  const gl = document.createElement('canvas').getContext('webgl2');\n  return gl != null && !gl.isContextLost() && gl.createTexture() != 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 texture') {\n    return <Video />;\n  }\n  throw err;\n}","preventionTips":["Probe texture allocation before mounting zigzag().","Render with Remotion's bundled Chromium; do not disable the software GPU.","Reduce concurrent WebGL effects to free texture 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-12T23:17:12.415Z"}