{"record":{"id":"d5d0f614ce24b0de","repo":"unoplatform/uno","slug":"program-failed-to-link-with-error-gl-getprogram","errorCode":null,"errorMessage":"Program failed to link with error: {_gl.GetProgramInfoLog(_handle)}","messagePattern":"Program failed to link with error: (.+?)","errorType":"exception","errorClass":"Exception","httpStatus":null,"severity":"critical","filePath":"src/SamplesApp/SamplesApp.Samples/Windows_UI_Composition/RotatingCubeGlCanvasElement.cs","lineNumber":182,"sourceCode":"\t\tpublic class Shader : IDisposable\n\t\t{\n\t\t\tprivate readonly uint _handle;\n\t\t\tprivate readonly GL _gl;\n\n\t\t\tpublic Shader(GL gl, string vertexShaderSource, string fragmentShaderSource)\n\t\t\t{\n\t\t\t\t_gl = gl;\n\n\t\t\t\tuint vertex = LoadShader(ShaderType.VertexShader, vertexShaderSource);\n\t\t\t\tuint fragment = LoadShader(ShaderType.FragmentShader, fragmentShaderSource);\n\t\t\t\t_handle = _gl.CreateProgram();\n\t\t\t\t_gl.AttachShader(_handle, vertex);\n\t\t\t\t_gl.AttachShader(_handle, fragment);\n\t\t\t\t_gl.LinkProgram(_handle);\n\t\t\t\t_gl.GetProgram(_handle, GLEnum.LinkStatus, out var status);\n\t\t\t\tif (status == 0)\n\t\t\t\t{\n\t\t\t\t\tthrow new Exception($\"Program failed to link with error: {_gl.GetProgramInfoLog(_handle)}\");\n\t\t\t\t}\n\t\t\t\t_gl.DetachShader(_handle, vertex);\n\t\t\t\t_gl.DetachShader(_handle, fragment);\n\t\t\t\t_gl.DeleteShader(vertex);\n\t\t\t\t_gl.DeleteShader(fragment);\n\t\t\t}\n\n\t\t\tpublic void Use()\n\t\t\t{\n\t\t\t\t_gl.UseProgram(_handle);\n\t\t\t}\n\n\t\t\tpublic void SetUniform(string name, int value)\n\t\t\t{\n\t\t\t\tint location = _gl.GetUniformLocation(_handle, name);\n\t\t\t\tif (location == -1)\n\t\t\t\t{\n\t\t\t\t\tthrow new Exception($\"{name} uniform not found on shader.\");","sourceCodeStart":164,"sourceCodeEnd":200,"githubUrl":"https://github.com/unoplatform/uno/blob/04183404888ea21b4e5bfa3493e8d5f15e972c3a/src/SamplesApp/SamplesApp.Samples/Windows_UI_Composition/RotatingCubeGlCanvasElement.cs#L164-L200","documentation":"The nested Shader class in RotatingCubeGlCanvasElement compiles+links the vertex/fragment pair in its constructor and throws when gl.GetProgram(LinkStatus) returns 0 (the Silk.NET overload uses GLEnum.LinkStatus and writes status as int). Link failure here means the cube's transform shader cannot form a valid program, so no rendering is possible.","triggerScenarios":"In the Shader ctor: LoadShader(vertex) + LoadShader(fragment) + CreateProgram + AttachShader + AttachShader + LinkProgram + GetProgram(LinkStatus, out status); throw if status == 0 (lines 178-182). The vertex shader declares `uniform mat4 transform; in vec3 pos; in vec3 vertex_color; out vec3 color;` and the fragment declares `in vec3 color; out vec4 frag_color;`.","commonSituations":"The vertex uses `out vec3 color` and the fragment uses `in vec3 color` (these match) but a name/type mismatch elsewhere would link-fail; the versionDef (`#version 300 es` / `#version 330`) prepended in Init at line 111 differs from what the context supports — note the shader source bodies themselves omit a `#version` line, relying on the prepended directive; sampler/uniform component limits; both stages must share the same GLSL profile or link fails.","solutions":["Read the appended GetProgramInfoLog output for the specific link error.","Confirm the versionDef was actually prepended at line 111 (`versionDef + Environment.NewLine + _vertexShaderSource`) — if versionDef is empty or wrong, the body compiles under a default profile that may not match across stages.","Verify the vertex `out vec3 color` exactly matches the fragment `in vec3 color` (name + type + qualifier).","Check that `layout(location=0)` and `layout(location=1)` attribute declarations do not collide with each other or with built-in attributes on the context.","Link one stage at a time and check MAX_VERTEX_ATTRIBS to rule out attribute-count limits."],"exampleFix":"// before\n_gl.GetProgram(_handle, GLEnum.LinkStatus, out var status);\nif (status == 0)\n    throw new Exception($\"Program failed to link with error: {_gl.GetProgramInfoLog(_handle)}\");\n\n// after — surface the versionDef and stage names in the error\n_gl.GetProgram(_handle, GLEnum.LinkStatus, out var status);\nif (status == 0)\n{\n    var log = _gl.GetProgramInfoLog(_handle);\n    throw new Exception($\"Program link failed [vs head='{vertexShaderSource[..Math.Min(20, vertexShaderSource.Length)]}']: {log}\");\n}","handlingStrategy":"validation","validationCode":"// Confirm versionDef was prepended and that both stages share it\nif (string.IsNullOrWhiteSpace(versionDef)) return; // body has no #version line; link will default-profile-fail\nif (!vertexShaderSource.Contains(\"out vec3 color\") || !FragmentShaderSource.Contains(\"in vec3 color\")) return; // interface mismatch","typeGuard":null,"tryCatchPattern":"try { _shader = new Shader(Gl, vs, fs); }\ncatch (Exception ex) when (ex.Message.Contains(\"Program failed to link\"))\n{\n    App.MainWindow?.LogError($\"Cube shader link failed: {ex.Message}\");\n    _shader = null;\n}","preventionTips":["Ensure the prepended #version directive matches the context's ShadingLanguageVersion.","Match vertex `out` and fragment `in` declarations exactly (name, type).","Avoid layout(location) collisions across attributes.","Check the program linked successfully before any SetUniform call."],"tags":["opengl","silk-net","glsl","shader-link","shader-program"],"backgroundTag":null,"analyzedSha":"04183404888ea21b4e5bfa3493e8d5f15e972c3a","analyzedAt":"2026-08-13T21:08:11.651Z","schemaVersion":2},"datasetVersion":"2026-08-14T00:17:13.853Z"}