{"record":{"id":"ef551d093c780ea8","repo":"DavidHDev/react-bits","slug":"unable-to-initialize-webgl","errorCode":null,"errorMessage":"Unable to initialize WebGL.","messagePattern":"Unable to initialize WebGL\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"critical","filePath":"src/ts-default/Animations/SplashCursor/SplashCursor.tsx","lineNumber":133,"sourceCode":"\n    function getWebGLContext(canvas: HTMLCanvasElement) {\n      const params = {\n        alpha: true,\n        depth: false,\n        stencil: false,\n        antialias: false,\n        preserveDrawingBuffer: false\n      };\n\n      let gl = canvas.getContext('webgl2', params) as WebGL2RenderingContext | null;\n\n      if (!gl) {\n        gl = (canvas.getContext('webgl', params) ||\n          canvas.getContext('experimental-webgl', params)) as WebGL2RenderingContext | null;\n      }\n\n      if (!gl) {\n        throw new Error('Unable to initialize WebGL.');\n      }\n\n      const isWebGL2 = 'drawBuffers' in gl;\n\n      let supportLinearFiltering = false;\n      let halfFloat: OES_texture_half_float | null = null;\n\n      if (isWebGL2) {\n        (gl as WebGL2RenderingContext).getExtension('EXT_color_buffer_float');\n        supportLinearFiltering = !!(gl as WebGL2RenderingContext).getExtension('OES_texture_float_linear');\n      } else {\n        halfFloat = gl.getExtension('OES_texture_half_float');\n        supportLinearFiltering = !!gl.getExtension('OES_texture_half_float_linear');\n      }\n\n      gl.clearColor(0, 0, 0, 1);\n\n      const halfFloatTexType = isWebGL2","sourceCodeStart":115,"sourceCodeEnd":151,"githubUrl":"https://github.com/DavidHDev/react-bits/blob/c7109dccb42e06592d1d9bc50bc87204697240e2/src/ts-default/Animations/SplashCursor/SplashCursor.tsx#L115-L151","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Use a real headless browser with GL (Chromium with SwiftShader/ANGLE) for tests instead of jsdom.","Verify WebGL is enabled in the user's browser (chrome://gpu, about:support).","Re-enable WebGL if disabled via blacklist by updating drivers or removing the blocklist override.","Guard the effect: only mount SplashCursor when a GL context is available, else render nothing/static."],"exampleFix":"// before\nconst { gl, ext } = getWebGLContext(canvas);\n\n// after\nfunction supportsWebGL() {\n  const c = document.createElement('canvas');\n  return !!(c.getContext('webgl2') || c.getContext('webgl') || c.getContext('experimental-webgl'));\n}\nif (!supportsWebGL()) return null; // skip mounting SplashCursor","handlingStrategy":"validation","validationCode":"function supportsAnyWebGL(): boolean {\n  const c = document.createElement('canvas');\n  try {\n    return !!(c.getContext('webgl2') || c.getContext('webgl') || c.getContext('experimental-webgl'));\n  } catch {\n    return false;\n  }\n}\n// before mounting SplashCursor:\nif (!supportsAnyWebGL()) return null;","typeGuard":"function getGL(canvas: HTMLCanvasElement): WebGLRenderingContext | WebGL2RenderingContext | null {\n  return (canvas.getContext('webgl2') ||\n    canvas.getContext('webgl') ||\n    canvas.getContext('experimental-webgl')) as WebGLRenderingContext | null;\n}","tryCatchPattern":null,"preventionTips":["Detect any WebGL support at boot and skip SplashCursor when none exists.","In tests use a GL-capable headless Chromium rather than jsdom.","Confirm WebGL is enabled (not blocklisted) in the user's browser via chrome://gpu.","Render a plain cursor as fallback when no GL context is available."],"tags":["webgl","gpu","context","initialization","browser-support","splashcursor"],"backgroundTag":null,"analyzedSha":"c7109dccb42e06592d1d9bc50bc87204697240e2","analyzedAt":"2026-08-13T02:32:07.327Z","schemaVersion":2},"datasetVersion":"2026-08-13T04:17:16.726Z"}