sickn33/agentic-awesome-skills · error
WebGL context unavailable
Error message
WebGL context unavailable
What it means
The spectral-field renderer's constructor calls canvas.getContext('webgl', {...}) and throws immediately if the context is null: the browser refused to create a WebGL1 context — disabled, blocklisted, or exhausted.
Source
Thrown at skills/liuguang-banlan-ui/assets/starter/shared/spectral-field.js:262
this.available = false;
this.error = null;
this.motionPreference = window.matchMedia("(prefers-reduced-motion: reduce)");
this.motionEnabled = !this.motionPreference.matches;
this.visible = !document.hidden;
this.startTime = performance.now();
this.phaseTime = null;
this.lastFrame = 0;
this.frameHandle = 0;
try {
this.gl = canvas.getContext("webgl", {
alpha: false,
antialias: false,
depth: false,
stencil: false,
powerPreference: "low-power",
preserveDrawingBuffer: true
});
if (!this.gl) throw new Error("WebGL context unavailable");
this.program = createProgram(this.gl);
this.gl.useProgram(this.program);
const buffer = this.gl.createBuffer();
if (!buffer) throw new Error("WebGL buffer creation failed");
this.gl.bindBuffer(this.gl.ARRAY_BUFFER, buffer);
this.gl.bufferData(
this.gl.ARRAY_BUFFER,
new Float32Array([-1, -1, 1, -1, -1, 1, -1, 1, 1, -1, 1, 1]),
this.gl.STATIC_DRAW
);
const position = this.gl.getAttribLocation(this.program, "aPosition");
if (position < 0) throw new Error("WebGL position attribute unavailable");
this.gl.enableVertexAttribArray(position);
this.gl.vertexAttribPointer(position, 2, this.gl.FLOAT, false, 0, 0);
this.locations = {
resolution: uniform(this.gl, this.program, "uResolution"),View on GitHub (pinned to 58d857988f)
Solutions
- Feature-detect WebGL before mounting and fall back to a 2D-canvas/CSS animation
- For headless tests, launch Chrome with --enable-unsafe-swiftshader or --use-gl=swiftshader
- Reuse one instance/canvas; call WEBGL_lose_context.loseContext() on teardown
- Ask desktop users to re-enable hardware acceleration
Example fix
// before
const gl = canvas.getContext('webgl', opts);
if (!gl) throw new Error('WebGL context unavailable');
// after
const gl = canvas.getContext('webgl', opts) || canvas.getContext('experimental-webgl', opts);
if (!gl) return SpectralField.cssFallback(canvas); Defensive patterns
Strategy: fallback
Validate before calling
const probe = document.createElement('canvas');
const supported = !!(probe.getContext('webgl') || probe.getContext('experimental-webgl'));
if (!supported) mountCssFallback(el); else new SpectralField(el); Type guard
function webglSupported(): boolean {
try {
const c = document.createElement('canvas');
return !!(window.WebGLRenderingContext && (c.getContext('webgl') || c.getContext('experimental-webgl')));
} catch { return false; }
} Try / catch
try { renderer = new SpectralField(canvas); }
catch (e) {
if (e.message === 'WebGL context unavailable') { renderer = null; mountCssFallback(canvas); }
else throw e;
} Prevention
- Feature-detect WebGL before mounting GL components
- Give headless tests SwiftShader flags
- Always ship a CSS/canvas2d fallback for decorative effects
- Reuse contexts instead of one per instance
When it happens
Trigger: Instantiating the renderer where getContext('webgl') returns null: hardware acceleration disabled in the browser, GPU blocklisted (some Linux/VM setups), too many live WebGL contexts already open, or a headless test environment without GPU support.
Common situations: Users with hardware acceleration off; headless Jest/Playwright runs without SwiftShader; VMs and remote desktops; pages that spawn many canvases and leak contexts.
Related errors
- WebGL buffer creation failed
- Shader compilation failed: ${message}
- Shader link failed: ${gl.getProgramInfoLog(program)}
AI-assisted analysis of sickn33/agentic-awesome-skills@58d857988f (2026-08-26).
Data as JSON: /api/errors/e520c6388eae1cef.
Report an issue: GitHub.