pbakaus/impeccable · error · Error
shader compile failed: ${info}
Error message
shader compile failed: ${info} What it means
compileShader throws this when a WebGL shader fails to compile: gl.getShaderParameter(sh, gl.COMPILE_STATUS) is false. It includes the driver's gl.getShaderInfoLog output so the offending GLSL line/syntax is identifiable, and deletes the failed shader before throwing.
Source
Thrown at skill/scripts/live-browser.js:8511
let r = 0, g = 0, b = 0, n = 0;
for (const [px, py] of pts) {
const cx = Math.max(0, Math.min(W - 1, Math.round(px)));
const cy = Math.max(0, Math.min(H - 1, Math.round(py)));
const d = ctx.getImageData(cx, cy, 1, 1).data;
if (d[3] === 0) continue; // outside the ancestor's paint
r += d[0]; g += d[1]; b += d[2]; n++;
}
return n ? [r / n / 255, g / n / 255, b / n / 255] : null;
}
function compileShader(gl, type, source) {
const sh = gl.createShader(type);
gl.shaderSource(sh, source);
gl.compileShader(sh);
if (!gl.getShaderParameter(sh, gl.COMPILE_STATUS)) {
const info = gl.getShaderInfoLog(sh);
gl.deleteShader(sh);
throw new Error('shader compile failed: ' + info);
}
return sh;
}
function positionShaderOverlay() {
if (!shaderState) return;
const anchor = resolveBarAnchor();
if (!anchor) return;
const r = anchor.getBoundingClientRect();
Object.assign(shaderState.canvas.style, {
top: r.top + 'px', left: r.left + 'px',
width: r.width + 'px', height: r.height + 'px',
});
}
/** Drop a shader node no shaderState owns (an abandoned construction). */
function removeStrayShaderNode() {
const stray = uiGetById(PREFIX + '-shader');View on GitHub (pinned to 2bc2879276)
Solutions
- Read the info log appended to the message — it names the GLSL line and error
- Validate the shader source for GLSL ES compatibility (avoid ES 3.00 syntax on a WebGL1 context)
- Test on another machine/browser to isolate driver-specific compile failures
- Check that context creation requested the needed attributes (antialias, precision) and that precision qualifiers are declared
Example fix
// before
const info = gl.getShaderInfoLog(sh);
throw new Error('shader compile failed: ' + info);
// after
const info = gl.getShaderInfoLog(sh);
console.error('shader source:\n' + source.split('\n').map((l,i)=>(i+1)+': '+l).join('\n'));
throw new Error('shader compile failed: ' + info); Defensive patterns
Strategy: try-catch
Validate before calling
// preflight: compile in a scratch context before committing the effect const test = gl.createShader(gl.FRAGMENT_SHADER); gl.shaderSource(test, SHADER_FS); gl.compileShader(test); if (!gl.getShaderParameter(test, gl.COMPILE_STATUS)) console.warn(gl.getShaderInfoLog(test));
Try / catch
try {
initShaderOverlay();
} catch (err) {
if (err.message.startsWith('shader compile failed')) {
console.error(err.message); // includes the GLSL info log
showToast('GPU shader unsupported on this device; falling back to CSS.');
}
} Prevention
- Read the info log — it points at the exact GLSL line and token
- Keep GLSL ES 1.00-compatible unless the context is explicitly WebGL2
- Test effects on low-end/software GL renderers before shipping
- Declare precision qualifiers and avoid driver-fragile constructs (dynamic loops, non-constant indices)
When it happens
Trigger: The shader source (e.g. the halftone SHADER_FS/vertex shader) contains GLSL that the GPU/driver rejects — syntax errors, unsupported GLSL version/extension, or uniform/varying mismatches on a specific machine's driver.
Common situations: Users on old or buggy GPU drivers rejecting otherwise-valid GLSL; headless or software renderers (SwiftShader limits); a code change introducing a GLSL typo or an ES 3.0 construct on an ES 1.0 context.
Related errors
- program link failed: ${gl.getProgramInfoLog(program)}
- [impeccable] shader setup failed:
- [impeccable] shader bitmap decode failed:
- No painted ancestor for Svelte shader proxy
AI-assisted analysis of pbakaus/impeccable@2bc2879276 (2026-09-08).
Data as JSON: /api/errors/b73ca51743f69eaf.
Report an issue: GitHub.