pbakaus/impeccable · error · Error

program link failed: ${gl.getProgramInfoLog(program)}

Error message

program link failed: ${gl.getProgramInfoLog(program)}

What it means

Thrown when the WebGL program built from the compiled vertex + fragment shaders fails to link: gl.getProgramParameter(program, gl.LINK_STATUS) is false. The message embeds gl.getProgramInfoLog(program), which typically reports mismatched varyings/uniforms or resource limits between the two shader stages.

Source

Thrown at skill/scripts/live-browser.js:8619

            || canvas.getContext('experimental-webgl');
    if (!gl) {
      // WebGL unavailable: use the captured bitmap as a background overlay so
      // the user still sees something meaningful during generation.
      if (abandoned(canvas, null)) return;
      showShaderBitmapFallback(canvas, blob);
      return;
    }

    let program, texture;
    try {
      const vs = compileShader(gl, gl.VERTEX_SHADER, SHADER_VS);
      const fs = compileShader(gl, gl.FRAGMENT_SHADER, SHADER_FS);
      program = gl.createProgram();
      gl.attachShader(program, vs);
      gl.attachShader(program, fs);
      gl.linkProgram(program);
      if (!gl.getProgramParameter(program, gl.LINK_STATUS)) {
        throw new Error('program link failed: ' + gl.getProgramInfoLog(program));
      }
      // Full-screen quad
      const buf = gl.createBuffer();
      gl.bindBuffer(gl.ARRAY_BUFFER, buf);
      gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([
        -1, -1, 0, 1,
         1, -1, 1, 1,
        -1,  1, 0, 0,
        -1,  1, 0, 0,
         1, -1, 1, 1,
         1,  1, 1, 0,
      ]), gl.STATIC_DRAW);
      const posLoc = gl.getAttribLocation(program, 'a_position');
      const uvLoc = gl.getAttribLocation(program, 'a_uv');
      gl.enableVertexAttribArray(posLoc);
      gl.vertexAttribPointer(posLoc, 2, gl.FLOAT, false, 16, 0);
      gl.enableVertexAttribArray(uvLoc);
      gl.vertexAttribPointer(uvLoc, 2, gl.FLOAT, false, 16, 8);

View on GitHub (pinned to 2bc2879276)

Solutions

  1. Read the program info log in the message — it names the linking incompatibility
  2. Ensure varyings/attributes used in the fragment shader are declared identically in the vertex shader
  3. Confirm both shaders compiled (compileShader would have thrown first) and were attached before linkProgram
  4. Revert recent GLSL edits and re-apply incrementally to find the mismatching declaration
Defensive patterns

Strategy: try-catch

Validate before calling

gl.linkProgram(program);
if (!gl.getProgramParameter(program, gl.LINK_STATUS)) {
  console.warn(gl.getProgramInfoLog(program));
}

Try / catch

try {
  program = createShaderProgram(gl, SHADER_VS, SHADER_FS);
} catch (err) {
  if (err.message.startsWith('program link failed')) {
    console.error(err.message);
    showToast('Shader program unavailable on this GPU; disabling the effect.');
  }
}

Prevention

When it happens

Trigger: attachShader + linkProgram on a valid context where the vertex and fragment shaders are incompatible (e.g. a varying written in the vertex shader but declared with a different type, or not declared, in the fragment shader), or the program exceeds driver limits.

Common situations: Editing SHADER_FS or the vertex shader so their varying/interface declarations diverge; drivers that reject implicit conversions; running on devices with restrictive shader resource limits.

Related errors


AI-assisted analysis of pbakaus/impeccable@2bc2879276 (2026-09-08). Data as JSON: /api/errors/fbd4102db395f023. Report an issue: GitHub.