unoplatform/uno · error · Exception

{name} uniform not found on shader.

Error message

{name} uniform not found on shader.

What it means

The int overload of Shader.SetUniform in RotatingCubeGlCanvasElement looks up a uniform by name and throws if gl.GetUniformLocation returns -1. A -1 means the uniform does not exist in the linked program — either the name is misspelled, the uniform was declared but optimized out by the compiler, or the wrong program is bound.

Source

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

					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.");
				}
				_gl.Uniform1(location, value);
			}

			public unsafe void SetUniform(string name, Matrix4x4 value)
			{
				//A new overload has been created for setting a uniform so we can use the transform in our shader.
				int location = _gl.GetUniformLocation(_handle, name);
				if (location == -1)
				{
					throw new Exception($"{name} uniform not found on shader.");
				}
				_gl.UniformMatrix4(location, 1, false, (float*)&value);
			}

			public void SetUniform(string name, float value)
			{
				int location = _gl.GetUniformLocation(_handle, name);

View on GitHub (pinned to 0418340488)

Solutions

  1. Confirm the uniform name matches a declared, used uniform in the shader source — for the cube, only `transform` exists, so int-typed SetUniform calls are inherently invalid.
  2. Use the uniform in the shader body so the compiler keeps it active; an unused uniform is pruned and returns -1 by spec.
  3. Cache uniform locations at construction time (after link) rather than looking them up per-call, so a missing uniform fails fast at Init with context, not at render time.
  4. Downgrade the throw to a no-op + log if the uniform is optional, since GetUniformLocation returning -1 for an inactive uniform is defined behavior, not an error.
  5. Verify the program was linked successfully (error 95) before any SetUniform call — a failed link leaves _handle in an unusable state.

Example fix

// before
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.");
    _gl.Uniform1(location, value);
}

// after — cache locations, tolerate optional uniforms, log instead of throw
private readonly Dictionary<string, int> _locs = new();
private int Loc(string name)
{
    if (_locs.TryGetValue(name, out var l)) return l;
    l = _gl.GetUniformLocation(_handle, name);
    _locs[name] = l;
    if (l == -1) System.Diagnostics.Debug.WriteLine($"Uniform '{name}' inactive or missing — set ignored");
    return l;
}
public void SetUniform(string name, int value)
{
    var l = Loc(name);
    if (l != -1) _gl.Uniform1(l, value);
}
Defensive patterns

Strategy: validation

Validate before calling

// Cache locations at construction; tolerate inactive uniforms instead of throwing
private readonly Dictionary<string, int> _locs = new();
public int Loc(string name)
{
    if (_locs.TryGetValue(name, out var l)) return l;
    l = _gl.GetUniformLocation(_handle, name);
    _locs[name] = l;
    return l; // -1 means inactive; caller decides
}
public void SetUniform(string name, int value)
{
    var l = Loc(name);
    if (l != -1) _gl.Uniform1(l, value);
}

Try / catch

try { _shader.SetUniform("texUnit", 0); }
catch (Exception ex) when (ex.Message.Contains("uniform not found"))
{
    // Non-fatal: uniform inactive or misspelled
    App.MainWindow?.LogError(ex.Message);
}

Prevention

When it happens

Trigger: Inside SetUniform(string name, int value): _gl.GetUniformLocation(_handle, name) == -1 (lines 197-200). The cube shader only declares one uniform (`mat4 transform`), so any int-typed SetUniform call would inherently hit this — there is no `int` uniform declared in the shader source.

Common situations: Calling SetUniform with a uniform name that is not declared in the GLSL (e.g. an int sampler name when only `transform` exists); the uniform was declared but unused, so the GLSL compiler pruned it and GetUniformLocation legitimately returns -1 (this is defined behavior, not a bug); typo in the name; the program was not linked / linked unsuccessfully; calling SetUniform before Use() (location lookup does not require Use, but a stale _handle would).

Related errors


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