siyuan-note/siyuan · error · Error

Unable to link graph shader

Error message

Unable to link graph shader

What it means

createProgram() throws when gl.LINK_STATUS is false after gl.linkProgram. The info log (or the fallback 'Unable to link graph shader') becomes the error message. Linking fails when compiled vertex/fragment shaders are individually valid but incompatible (mismatched varying declarations, missing uniforms, or GLSL ES version inconsistencies).

Source

Thrown at app/src/layout/dock/graph/webglRenderer.ts:484

    private setViewUniforms(program: WebGLProgram, state: IGraphRenderState) {
        this.gl.uniform2f(this.getUniform(program, "u_viewport"), state.width, state.height);
        this.gl.uniform3f(this.getUniform(program, "u_camera"), state.camera.x, state.camera.y, state.camera.scale);
    }

    private createProgram(vertexSource: string, fragmentSource: string) {
        const gl = this.gl;
        const program = this.requireValue(gl.createProgram());
        const vertex = this.createShader(gl.VERTEX_SHADER, vertexSource);
        const fragment = this.createShader(gl.FRAGMENT_SHADER, fragmentSource);
        gl.attachShader(program, vertex);
        gl.attachShader(program, fragment);
        gl.linkProgram(program);
        gl.deleteShader(vertex);
        gl.deleteShader(fragment);
        if (!gl.getProgramParameter(program, gl.LINK_STATUS)) {
            const message = gl.getProgramInfoLog(program) || "Unable to link graph shader";
            gl.deleteProgram(program);
            throw new Error(message);
        }
        return program;
    }

    private createShader(type: number, source: string) {
        const gl = this.gl;
        const shader = this.requireValue(gl.createShader(type));
        gl.shaderSource(shader, source);
        gl.compileShader(shader);
        if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
            const message = gl.getShaderInfoLog(shader) || "Unable to compile graph shader";
            gl.deleteShader(shader);
            throw new Error(message);
        }
        return shader;
    }

    private getUniform(program: WebGLProgram, name: string) {

View on GitHub (pinned to 251596fc0d)

Solutions

  1. Inspect the thrown message — it is gl.getProgramInfoLog output and names the exact linking error.
  2. Re-read the vertex/fragment shader pair to confirm every vertex 'out' has a matching fragment 'in' of the same type.
  3. Verify the shaders still start with '#version 300 es' and use GLSL ES 3.00 syntax (in/out, not attribute/varying).
  4. Reproduce on a second GPU/driver to rule out a driver-specific linker bug.

Example fix

// before
if (!gl.getProgramParameter(program, gl.LINK_STATUS)) {
    throw new Error(gl.getProgramInfoLog(program) || 'Unable to link graph shader');
}
// after (surface and continue without crashing the dock)
if (!gl.getProgramParameter(program, gl.LINK_STATUS)) {
    console.error('shader link failed:', gl.getProgramInfoLog(program));
    gl.deleteProgram(program);
    showGraphFallback();
    return null;
}
Defensive patterns

Strategy: try-catch

Try / catch

try { return new WebGLRenderer(canvas); }
catch (e) {
    console.error('graph shader link failed:', e.message);
    showGraphFallback();
    return null;
}

Prevention

When it happens

Trigger: A change to the inline NODE_/EDGE_/ARROW_ shader sources breaks the vertex/fragment contract (e.g. an 'in' declared in the fragment but not 'out' in the vertex); running on a driver that rejects the program even though the sources compile; uniform name typos between getUniform lookups and shader source.

Common situations: Developer edits the inline GLSL in webglRenderer.ts and forgets to update both vertex and fragment pairs; a GPU driver bug refuses linking for specific feature combinations; running on older mobile GPUs with stricter linking rules.

Related errors


AI-assisted analysis of siyuan-note/siyuan@251596fc0d (2026-08-12). Data as JSON: /api/errors/02f0a04e9ee6e73c. Report an issue: GitHub.