sickn33/agentic-awesome-skills · error
Shader link failed: ${gl.getProgramInfoLog(program)}
Error message
Shader link failed: ${gl.getProgramInfoLog(program)} What it means
createProgram attaches the compiled vertex and fragment shaders, calls gl.linkProgram, and throws when LINK_STATUS is false, embedding the program info log. Link failures occur even when both shaders compiled — usually mismatched varying names or precision between stages, or too many varyings for the GPU.
Source
Thrown at skills/liuguang-banlan-ui/assets/starter/shared/spectral-field.js:230
function compileShader(gl, type, source) {
const shader = gl.createShader(type);
gl.shaderSource(shader, source);
gl.compileShader(shader);
if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
const message = gl.getShaderInfoLog(shader);
gl.deleteShader(shader);
throw new Error(`Shader compilation failed: ${message}`);
}
return shader;
}
function createProgram(gl) {
const program = gl.createProgram();
gl.attachShader(program, compileShader(gl, gl.VERTEX_SHADER, VERTEX_SHADER));
gl.attachShader(program, compileShader(gl, gl.FRAGMENT_SHADER, FRAGMENT_SHADER));
gl.linkProgram(program);
if (!gl.getProgramParameter(program, gl.LINK_STATUS)) {
throw new Error(`Shader link failed: ${gl.getProgramInfoLog(program)}`);
}
return program;
}
function uniform(gl, program, name) {
return gl.getUniformLocation(program, name);
}
class SpectralField {
constructor(canvas, config) {
this.canvas = canvas;
this.config = config;
this.applyFallbackConfig(config);
this.available = false;
this.error = null;
this.motionPreference = window.matchMedia("(prefers-reduced-motion: reduce)");
this.motionEnabled = !this.motionPreference.matches;
this.visible = !document.hidden;View on GitHub (pinned to 58d857988f)
Solutions
- Read the info log — it typically names the missing/undeclared varying in one stage
- Make varying names and precision identical in both shader strings
- Keep varying count under ~8 vectors for broad mobile support
- Ensure the vertex shader writes gl_Position on every code path
Example fix
// before // vertex: varying vec2 vUv; // fragment: varying vec2 v_uv; // mismatch -> link error // after // vertex: varying vec2 vUv; // fragment: varying vec2 vUv;
Defensive patterns
Strategy: try-catch
Try / catch
try { program = createProgram(gl); }
catch (e) {
if (/Shader link failed/.test(e.message)) { console.error(e.message); return useFallbackRenderer(canvas); }
throw e;
} Prevention
- Keep varying names and precision identical across both shader stages
- Change shader interfaces in both files in the same commit
- Check varying count against gl.getParameter(gl.MAX_VARYING_VECTORS)
When it happens
Trigger: Renaming a varying in VERTEX_SHADER but not FRAGMENT_SHADER (or vice versa); different precision qualifiers on a shared varying; exceeding MAX_VARYING_VECTORS; a vertex shader path that skips writing gl_Position.
Common situations: Customizing the pass and editing only one of the two shader strings; porting a shader pair from another demo with different interface names; low-end mobile GPUs with small varying limits.
Related errors
AI-assisted analysis of sickn33/agentic-awesome-skills@58d857988f (2026-08-26).
Data as JSON: /api/errors/c941ce75cca7658c.
Report an issue: GitHub.