{"record":{"id":"68f37f33f8903eb2","repo":"DavidHDev/react-bits","slug":"failed-to-create-webgl-texture","errorCode":null,"errorMessage":"Failed to create WebGL texture.","messagePattern":"Failed to create WebGL texture\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"src/ts-default/Components/InfiniteMenu/InfiniteMenu.tsx","lineNumber":474,"sourceCode":"    gl.bufferData(gl.ARRAY_BUFFER, sizeOrData, usage);\n  } else {\n    gl.bufferData(gl.ARRAY_BUFFER, sizeOrData, usage);\n  }\n\n  gl.bindBuffer(gl.ARRAY_BUFFER, null);\n  return buf;\n}\n\nfunction createAndSetupTexture(\n  gl: WebGL2RenderingContext,\n  minFilter: number,\n  magFilter: number,\n  wrapS: number,\n  wrapT: number\n): WebGLTexture {\n  const texture = gl.createTexture();\n  if (!texture) {\n    throw new Error('Failed to create WebGL texture.');\n  }\n  gl.bindTexture(gl.TEXTURE_2D, texture);\n  gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, wrapS);\n  gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, wrapT);\n  gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, minFilter);\n  gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, magFilter);\n  return texture;\n}\n\ntype UpdateCallback = (deltaTime: number) => void;\n\nclass ArcballControl {\n  private canvas: HTMLCanvasElement;\n  private updateCallback: UpdateCallback;\n\n  public isPointerDown = false;\n  public orientation = quat.create();\n  public pointerRotation = quat.create();","sourceCodeStart":456,"sourceCodeEnd":492,"githubUrl":"https://github.com/DavidHDev/react-bits/blob/c7109dccb42e06592d1d9bc50bc87204697240e2/src/ts-default/Components/InfiniteMenu/InfiniteMenu.tsx#L456-L492","documentation":"createAndSetupTexture throws when gl.createTexture() returns null. Like createBuffer, createTexture returns null on a lost context or exhausted texture pool. InfiniteMenu creates textures for the scene, so a null here during init blocks the component from rendering.","triggerScenarios":"gl.createTexture() returns null at src/ts-default/Components/InfiniteMenu/InfiniteMenu.tsx:467 inside createAndSetupTexture, typically during init() or after a resize-driven re-allocation while the GL context is lost.","commonSituations":"Many simultaneous WebGL components on the page (context/object pool exhaustion); a recent webglcontextlost event not yet restored; GPU process crash; mobile/embedded GPUs with tight texture limits; rapid mount/unmount cycles leaking textures (missing gl.deleteTexture).","solutions":["Handle 'webglcontextlost'/'webglcontextrestored' and avoid allocating textures during loss.","Dispose textures on unmount (gl.deleteTexture) to prevent pool exhaustion from leaks.","Limit the number of live InfiniteMenu/WebGL instances on the page.","If persistent, switch to a fallback rendering path and report the unsupported environment."],"exampleFix":"// before\nconst texture = gl.createTexture();\nif (!texture) throw new Error('Failed to create WebGL texture.');\n\n// after\n// only allocate when context is healthy; clean up on unmount\nuseEffect(() => {\n  const onLost = (e: Event) => { e.preventDefault(); };\n  canvas.addEventListener('webglcontextlost', onLost);\n  return () => {\n    canvas.removeEventListener('webglcontextlost', onLost);\n    if (texture) gl.deleteTexture(texture);\n  };\n}, []);","handlingStrategy":"try-catch","validationCode":"function contextHealthy(gl: WebGL2RenderingContext): boolean {\n  return !gl.isContextLost();\n}","typeGuard":"function canCreateTexture(gl: WebGL2RenderingContext): boolean {\n  const probe = gl.createTexture();\n  if (probe) { gl.deleteTexture(probe); return true; }\n  return false;\n}","tryCatchPattern":"canvas.addEventListener('webglcontextlost', (e) => e.preventDefault());\ntry {\n  return createAndSetupTexture(gl, minFilter, magFilter, wrapS, wrapT);\n} catch (e) {\n  if (e instanceof Error && /WebGL texture/.test(e.message)) return null;\n  throw e;\n}","preventionTips":["Dispose textures with gl.deleteTexture on unmount.","Cap the number of live WebGL/InfiniteMenu instances to avoid pool exhaustion.","Defer texture creation until after webglcontextrestored.","Render a fallback path if texture allocation persistently fails."],"tags":["webgl2","gpu","texture","context-loss","resource-limits","infinitemenu"],"backgroundTag":null,"analyzedSha":"c7109dccb42e06592d1d9bc50bc87204697240e2","analyzedAt":"2026-08-13T02:32:07.327Z","schemaVersion":2},"datasetVersion":"2026-08-13T04:17:16.726Z"}