{"record":{"id":"c941ce75cca7658c","repo":"sickn33/agentic-awesome-skills","slug":"shader-link-failed-gl-getprograminfolog-program","errorCode":null,"errorMessage":"Shader link failed: ${gl.getProgramInfoLog(program)}","messagePattern":"Shader link failed: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"skills/liuguang-banlan-ui/assets/starter/shared/spectral-field.js","lineNumber":230,"sourceCode":"  function compileShader(gl, type, source) {\n    const shader = gl.createShader(type);\n    gl.shaderSource(shader, source);\n    gl.compileShader(shader);\n    if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {\n      const message = gl.getShaderInfoLog(shader);\n      gl.deleteShader(shader);\n      throw new Error(`Shader compilation failed: ${message}`);\n    }\n    return shader;\n  }\n\n  function createProgram(gl) {\n    const program = gl.createProgram();\n    gl.attachShader(program, compileShader(gl, gl.VERTEX_SHADER, VERTEX_SHADER));\n    gl.attachShader(program, compileShader(gl, gl.FRAGMENT_SHADER, FRAGMENT_SHADER));\n    gl.linkProgram(program);\n    if (!gl.getProgramParameter(program, gl.LINK_STATUS)) {\n      throw new Error(`Shader link failed: ${gl.getProgramInfoLog(program)}`);\n    }\n    return program;\n  }\n\n  function uniform(gl, program, name) {\n    return gl.getUniformLocation(program, name);\n  }\n\n  class SpectralField {\n    constructor(canvas, config) {\n      this.canvas = canvas;\n      this.config = config;\n      this.applyFallbackConfig(config);\n      this.available = false;\n      this.error = null;\n      this.motionPreference = window.matchMedia(\"(prefers-reduced-motion: reduce)\");\n      this.motionEnabled = !this.motionPreference.matches;\n      this.visible = !document.hidden;","sourceCodeStart":212,"sourceCodeEnd":248,"githubUrl":"https://github.com/sickn33/agentic-awesome-skills/blob/58d857988fcfac6986206bca2b2fe223aa437e4b/skills/liuguang-banlan-ui/assets/starter/shared/spectral-field.js#L212-L248","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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"],"exampleFix":"// before\n// vertex:   varying vec2 vUv;\n// fragment: varying vec2 v_uv;   // mismatch -> link error\n\n// after\n// vertex:   varying vec2 vUv;\n// fragment: varying vec2 vUv;","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try { program = createProgram(gl); }\ncatch (e) {\n  if (/Shader link failed/.test(e.message)) { console.error(e.message); return useFallbackRenderer(canvas); }\n  throw e;\n}","preventionTips":["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)"],"tags":["webgl","glsl","shader-link","browser"],"backgroundTag":"shader-compilation-failed","analyzedSha":"58d857988fcfac6986206bca2b2fe223aa437e4b","analyzedAt":"2026-08-26T11:55:59.350Z","schemaVersion":2},"datasetVersion":"2026-08-26T14:46:13.012Z"}