{"record":{"id":"81b138013cf2ce09","repo":"remotion-dev/remotion","slug":"failed-to-create-webgl-texture-81b138","errorCode":null,"errorMessage":"Failed to create WebGL texture","messagePattern":"Failed to create WebGL texture","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"critical","filePath":"packages/effects/src/noise-displacement.ts","lineNumber":495,"sourceCode":"\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 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, gl.LINEAR);\n\tgl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);\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\n\treturn {\n\t\tgl,\n\t\tprogram,\n\t\tvao,\n\t\tvbo,\n\t\ttexture,\n\t\tuniforms: {\n\t\t\tuSource: gl.getUniformLocation(program, 'uSource'),\n\t\t\tuResolution: gl.getUniformLocation(program, 'uResolution'),","sourceCodeStart":477,"sourceCodeEnd":513,"githubUrl":"https://github.com/remotion-dev/remotion/blob/78fe4bb3fdb5a2cd68724393d63cb223db333fa7/packages/effects/src/noise-displacement.ts#L477-L513","documentation":"Thrown inside setupNoiseDisplacement (packages/effects/src/noise-displacement.ts:495) when gl.createTexture() returns null while creating the source texture used to upload each frame for the noiseDisplacement effect. Per the WebGL spec a null texture means the context is lost, GPU memory is exhausted, or the per-context texture count is maxed out. Setup is on the first apply, so this stops the Remotion render frame.","triggerScenarios":"noiseDisplacement({...}) running when the WebGL2 context is lost or GPU memory is exhausted; many effects allocating textures concurrently past the implementation's live-texture limit; rendering very large frame sizes that exhaust texture memory.","commonSituations":"Long-running Studio sessions that leak textures; GPU-less headless render hosts; mobile or integrated-GPU machines with low texture memory; a GPU process crash during a render batch.","solutions":["Make sure effect cleanup runs between compositions so gl.deleteTexture reclaims textures, and cap simultaneous WebGL2 effects.","Render on a GPU-equipped host (or enable WebGL in headless Chrome) so texture allocation succeeds.","Handle 'webglcontextlost' on the canvas and re-render after restoration.","Fall back to rendering the composition without noiseDisplacement on environments that cannot allocate the texture."],"exampleFix":"// before\nconst gl = canvas.getContext('webgl2');\nconst tex = gl.createTexture(); // returns null -> throws\n\n// after: detect allocation failure and degrade gracefully\nconst tex = gl.createTexture();\nif (!tex) {\n  throw new Error('noiseDisplacement unavailable on this GPU; falling back');\n}","handlingStrategy":"try-catch","validationCode":"function canAllocateNoiseDisplacementTexture(): boolean {\n  try {\n    const c = document.createElement('canvas');\n    const gl = c.getContext('webgl2');\n    if (!gl || gl.isContextLost()) return false;\n    const t = gl.createTexture();\n    const ok = !!t;\n    if (t) gl.deleteTexture(t);\n    return ok;\n  } catch {\n    return false;\n  }\n}","typeGuard":null,"tryCatchPattern":"try {\n  scene.push(noiseDisplacement({center: [0.5, 0.5], radius: 0.4}));\n} catch (err) {\n  if (/Failed to create WebGL texture/.test(String(err?.message))) {\n    // fall back: omit the effect\n  } else throw err;\n}","preventionTips":["Dispose textures via cleanup between compositions.","Limit concurrent WebGL2 effects and avoid huge frame sizes on low-memory GPUs.","Handle webglcontextlost/restored on the canvas.","Use GPU-enabled headless Chrome for renders that use WebGL2 effects."],"tags":["webgl","gpu","noise-displacement","effects","texture","context-loss"],"backgroundTag":null,"analyzedSha":"78fe4bb3fdb5a2cd68724393d63cb223db333fa7","analyzedAt":"2026-08-12T17:18:50.444Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}