DavidHDev/react-bits · error · Error

Failed to create WebGL texture.

Error message

Failed to create WebGL texture.

What it means

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.

Source

Thrown at src/ts-default/Components/InfiniteMenu/InfiniteMenu.tsx:474

    gl.bufferData(gl.ARRAY_BUFFER, sizeOrData, usage);
  } else {
    gl.bufferData(gl.ARRAY_BUFFER, sizeOrData, usage);
  }

  gl.bindBuffer(gl.ARRAY_BUFFER, null);
  return buf;
}

function createAndSetupTexture(
  gl: WebGL2RenderingContext,
  minFilter: number,
  magFilter: number,
  wrapS: number,
  wrapT: number
): WebGLTexture {
  const texture = gl.createTexture();
  if (!texture) {
    throw new Error('Failed to create WebGL texture.');
  }
  gl.bindTexture(gl.TEXTURE_2D, texture);
  gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, wrapS);
  gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, wrapT);
  gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, minFilter);
  gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, magFilter);
  return texture;
}

type UpdateCallback = (deltaTime: number) => void;

class ArcballControl {
  private canvas: HTMLCanvasElement;
  private updateCallback: UpdateCallback;

  public isPointerDown = false;
  public orientation = quat.create();
  public pointerRotation = quat.create();

View on GitHub (pinned to c7109dccb4)

Solutions

  1. Handle 'webglcontextlost'/'webglcontextrestored' and avoid allocating textures during loss.
  2. Dispose textures on unmount (gl.deleteTexture) to prevent pool exhaustion from leaks.
  3. Limit the number of live InfiniteMenu/WebGL instances on the page.
  4. If persistent, switch to a fallback rendering path and report the unsupported environment.

Example fix

// before
const texture = gl.createTexture();
if (!texture) throw new Error('Failed to create WebGL texture.');

// after
// only allocate when context is healthy; clean up on unmount
useEffect(() => {
  const onLost = (e: Event) => { e.preventDefault(); };
  canvas.addEventListener('webglcontextlost', onLost);
  return () => {
    canvas.removeEventListener('webglcontextlost', onLost);
    if (texture) gl.deleteTexture(texture);
  };
}, []);
Defensive patterns

Strategy: try-catch

Validate before calling

function contextHealthy(gl: WebGL2RenderingContext): boolean {
  return !gl.isContextLost();
}

Type guard

function canCreateTexture(gl: WebGL2RenderingContext): boolean {
  const probe = gl.createTexture();
  if (probe) { gl.deleteTexture(probe); return true; }
  return false;
}

Try / catch

canvas.addEventListener('webglcontextlost', (e) => e.preventDefault());
try {
  return createAndSetupTexture(gl, minFilter, magFilter, wrapS, wrapT);
} catch (e) {
  if (e instanceof Error && /WebGL texture/.test(e.message)) return null;
  throw e;
}

Prevention

When it happens

Trigger: 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.

Common situations: 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).

Related errors


AI-assisted analysis of DavidHDev/react-bits@c7109dccb4 (2026-08-13). Data as JSON: /api/errors/68f37f33f8903eb2. Report an issue: GitHub.