unoplatform/uno · critical · Exception

Program failed to link with error: {_gl.GetProgramInfoLog(_h

Error message

Program failed to link with error: {_gl.GetProgramInfoLog(_handle)}

What it means

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.

Source

Thrown at src/SamplesApp/SamplesApp.Samples/Windows_UI_Composition/RotatingCubeGlCanvasElement.cs:182

		public class Shader : IDisposable
		{
			private readonly uint _handle;
			private readonly GL _gl;

			public Shader(GL gl, string vertexShaderSource, string fragmentShaderSource)
			{
				_gl = gl;

				uint vertex = LoadShader(ShaderType.VertexShader, vertexShaderSource);
				uint fragment = LoadShader(ShaderType.FragmentShader, fragmentShaderSource);
				_handle = _gl.CreateProgram();
				_gl.AttachShader(_handle, vertex);
				_gl.AttachShader(_handle, fragment);
				_gl.LinkProgram(_handle);
				_gl.GetProgram(_handle, GLEnum.LinkStatus, out var status);
				if (status == 0)
				{
					throw new Exception($"Program failed to link with error: {_gl.GetProgramInfoLog(_handle)}");
				}
				_gl.DetachShader(_handle, vertex);
				_gl.DetachShader(_handle, fragment);
				_gl.DeleteShader(vertex);
				_gl.DeleteShader(fragment);
			}

			public void Use()
			{
				_gl.UseProgram(_handle);
			}

			public void SetUniform(string name, int value)
			{
				int location = _gl.GetUniformLocation(_handle, name);
				if (location == -1)
				{
					throw new Exception($"{name} uniform not found on shader.");

View on GitHub (pinned to 0418340488)

Solutions

  1. Read the appended GetProgramInfoLog output for the specific link error.
  2. 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.
  3. Verify the vertex `out vec3 color` exactly matches the fragment `in vec3 color` (name + type + qualifier).
  4. 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.
  5. Link one stage at a time and check MAX_VERTEX_ATTRIBS to rule out attribute-count limits.

Example fix

// before
_gl.GetProgram(_handle, GLEnum.LinkStatus, out var status);
if (status == 0)
    throw new Exception($"Program failed to link with error: {_gl.GetProgramInfoLog(_handle)}");

// after — surface the versionDef and stage names in the error
_gl.GetProgram(_handle, GLEnum.LinkStatus, out var status);
if (status == 0)
{
    var log = _gl.GetProgramInfoLog(_handle);
    throw new Exception($"Program link failed [vs head='{vertexShaderSource[..Math.Min(20, vertexShaderSource.Length)]}']: {log}");
}
Defensive patterns

Strategy: validation

Validate before calling

// Confirm versionDef was prepended and that both stages share it
if (string.IsNullOrWhiteSpace(versionDef)) return; // body has no #version line; link will default-profile-fail
if (!vertexShaderSource.Contains("out vec3 color") || !FragmentShaderSource.Contains("in vec3 color")) return; // interface mismatch

Try / catch

try { _shader = new Shader(Gl, vs, fs); }
catch (Exception ex) when (ex.Message.Contains("Program failed to link"))
{
    App.MainWindow?.LogError($"Cube shader link failed: {ex.Message}");
    _shader = null;
}

Prevention

When it happens

Trigger: 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;`.

Common situations: 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.

Related errors


AI-assisted analysis of unoplatform/uno@0418340488 (2026-08-13). Data as JSON: /api/errors/d5d0f614ce24b0de. Report an issue: GitHub.