{"record":{"id":"5ac7e01ad070faa4","repo":"remotion-dev/remotion","slug":"failed-to-create-webgl-texture-5ac7e0","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/paper.ts","lineNumber":696,"sourceCode":"\t\tthrow new Error('Failed to create WebGL program');\n\t}\n\n\tgl.attachShader(program, vs);\n\tgl.attachShader(program, fs);\n\tgl.linkProgram(program);\n\tif (!gl.getProgramParameter(program, gl.LINK_STATUS)) {\n\t\tconst log = gl.getProgramInfoLog(program);\n\t\tgl.deleteProgram(program);\n\t\tthrow new Error(`Paper program link failed: ${log ?? '(no log)'}`);\n\t}\n\n\treturn program;\n};\n\nconst createSourceTexture = (gl: WebGL2RenderingContext): 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, 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\treturn texture;\n};\n\nconst initialNoiseState = (seed: number): number => {\n\tconst scaledSeed = Math.round(seed * 1000);\n\tconst mixedState = (0x9e3779b9 ^ Math.imul(scaledSeed, 0x85ebca6b)) >>> 0;\n\treturn mixedState === 0 ? 0x9e3779b9 : mixedState;\n};\n\nconst nextNoiseState = (state: number): number => {","sourceCodeStart":678,"sourceCodeEnd":714,"githubUrl":"https://github.com/remotion-dev/remotion/blob/78fe4bb3fdb5a2cd68724393d63cb223db333fa7/packages/effects/src/paper.ts#L678-L714","documentation":"Thrown by createSourceTexture (packages/effects/src/paper.ts:696) when gl.createTexture() returns null while creating the source texture the paper effect uploads each frame into. Null indicates a lost WebGL2 context, GPU-memory exhaustion, or too many live textures.","triggerScenarios":"setupPaper creating the source texture on a lost context or under GPU-memory pressure; many texture-allocating effects running concurrently; very large render dimensions.","commonSituations":"Integrated GPUs with low texture memory; leaked textures in long sessions; headless software rendering; GPU crash mid-batch.","solutions":["Dispose textures via cleanup between compositions and cap concurrent WebGL2 effects.","Render on a GPU host with WebGL enabled in headless Chrome.","Handle context-loss events and re-render after restore; fall back to no-effect render if allocation keeps failing."],"exampleFix":"// before\nconst sourceTexture = createSourceTexture(gl); // createTexture() returned null\n\n// after\nif (gl.isContextLost()) {\n  throw new Error('WebGL2 context lost; cannot create paper source texture');\n}","handlingStrategy":"try-catch","validationCode":"function canCreatePaperSourceTexture(): 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(paper({amount: 1}));\n} catch (err) {\n  if (/Failed to create WebGL texture/.test(String(err?.message))) {\n    // texture budget exhausted or context lost: omit the effect\n  } else throw err;\n}","preventionTips":["Delete textures via cleanup between compositions.","Avoid very large frame sizes on low-memory GPUs.","Handle webglcontextlost/restored and use GPU-enabled headless Chrome."],"tags":["webgl","gpu","paper","effects","texture","context-loss"],"backgroundTag":null,"analyzedSha":"78fe4bb3fdb5a2cd68724393d63cb223db333fa7","analyzedAt":"2026-08-12T17:18:50.444Z","schemaVersion":2},"datasetVersion":"2026-08-12T18:17:37.767Z"}