DavidHDev/react-bits · critical · Error

Unable to initialize WebGL.

Error message

Unable to initialize WebGL.

What it means

SplashCursor.getWebGLContext tries webgl2, then falls back to 'webgl' and 'experimental-webgl' before giving up. Unlike the InfiniteMenu errors, this only fires when the browser exposes no WebGL of any version. The fluid simulation cannot run without a GL context, so it aborts.

Source

Thrown at src/ts-default/Animations/SplashCursor/SplashCursor.tsx:133

    function getWebGLContext(canvas: HTMLCanvasElement) {
      const params = {
        alpha: true,
        depth: false,
        stencil: false,
        antialias: false,
        preserveDrawingBuffer: false
      };

      let gl = canvas.getContext('webgl2', params) as WebGL2RenderingContext | null;

      if (!gl) {
        gl = (canvas.getContext('webgl', params) ||
          canvas.getContext('experimental-webgl', params)) as WebGL2RenderingContext | null;
      }

      if (!gl) {
        throw new Error('Unable to initialize WebGL.');
      }

      const isWebGL2 = 'drawBuffers' in gl;

      let supportLinearFiltering = false;
      let halfFloat: OES_texture_half_float | null = null;

      if (isWebGL2) {
        (gl as WebGL2RenderingContext).getExtension('EXT_color_buffer_float');
        supportLinearFiltering = !!(gl as WebGL2RenderingContext).getExtension('OES_texture_float_linear');
      } else {
        halfFloat = gl.getExtension('OES_texture_half_float');
        supportLinearFiltering = !!gl.getExtension('OES_texture_half_float_linear');
      }

      gl.clearColor(0, 0, 0, 1);

      const halfFloatTexType = isWebGL2

View on GitHub (pinned to c7109dccb4)

Solutions

  1. Use a real headless browser with GL (Chromium with SwiftShader/ANGLE) for tests instead of jsdom.
  2. Verify WebGL is enabled in the user's browser (chrome://gpu, about:support).
  3. Re-enable WebGL if disabled via blacklist by updating drivers or removing the blocklist override.
  4. Guard the effect: only mount SplashCursor when a GL context is available, else render nothing/static.

Example fix

// before
const { gl, ext } = getWebGLContext(canvas);

// after
function supportsWebGL() {
  const c = document.createElement('canvas');
  return !!(c.getContext('webgl2') || c.getContext('webgl') || c.getContext('experimental-webgl'));
}
if (!supportsWebGL()) return null; // skip mounting SplashCursor
Defensive patterns

Strategy: validation

Validate before calling

function supportsAnyWebGL(): boolean {
  const c = document.createElement('canvas');
  try {
    return !!(c.getContext('webgl2') || c.getContext('webgl') || c.getContext('experimental-webgl'));
  } catch {
    return false;
  }
}
// before mounting SplashCursor:
if (!supportsAnyWebGL()) return null;

Type guard

function getGL(canvas: HTMLCanvasElement): WebGLRenderingContext | WebGL2RenderingContext | null {
  return (canvas.getContext('webgl2') ||
    canvas.getContext('webgl') ||
    canvas.getContext('experimental-webgl')) as WebGLRenderingContext | null;
}

Prevention

When it happens

Trigger: All three getContext calls (webgl2, webgl, experimental-webgl) return null at src/ts-default/Animations/SplashCursor/SplashCursor.tsx:127-133. Note the caller at line 108-109 catches via early-return if getWebGLContext throws, so the throw propagates only if the caller doesn't destructure-safeguard.

Common situations: jsdom/happy-dom in unit tests (no GL); WebGL fully disabled via browser flags or blocklist; extremely old browsers; secure/locked-down kiosks; software-only environments with no GL driver at all.

Related errors


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