unoplatform/uno · error · Exception

ValidateProgram failed: {infoLog}

Error message

ValidateProgram failed: {infoLog}

What it means

gl.ValidateProgram checks whether _barsProgram can execute given the current GL state (sampler bindings, bound VAO, etc.) and writes VALIDATE_STATUS. A failed validation means the program would behave incorrectly or undefined in the current state — distinct from link status which only checks the program object in isolation. This sample validates at Init time as a self-check.

Source

Thrown at src/SamplesApp/SamplesApp.Samples/Windows_UI_Composition/QuerySyncGlCanvasElement.cs:157

			// Program introspection: enumerate active uniforms and validate the program.
			gl.GetProgram(_barsProgram, ProgramPropertyARB.ActiveUniforms, out int activeUniforms);
			var foundWave = false;
			for (uint i = 0; i < activeUniforms; i++)
			{
				var name = gl.GetActiveUniform(_barsProgram, i, out int size, out UniformType type);
				// Array uniforms report as "uWave[0]" with size = element count.
				foundWave |= name.StartsWith("uWave", StringComparison.Ordinal) && size == BarCount && type == UniformType.Float;
			}
			if (!foundWave)
			{
				throw new Exception($"GetActiveUniform did not report uWave[{BarCount}] (saw {activeUniforms} active uniforms)");
			}
			gl.ValidateProgram(_barsProgram);
			gl.GetProgram(_barsProgram, ProgramPropertyARB.ValidateStatus, out int validateStatus);
			if (validateStatus != (int)GLEnum.True)
			{
				throw new Exception("ValidateProgram failed: " + gl.GetProgramInfoLog(_barsProgram));
			}

			_query = gl.GenQuery();

			// Init must finish error-clean; surface anything the calls above raised.
			var err = gl.GetError();
			if (err != GLEnum.NoError)
			{
				throw new Exception($"GL error at end of Init: 0x{(int)err:x}");
			}
		}

		protected override void OnDestroy(GL gl)
		{
			gl.DeleteVertexArray(_barsVao);
			gl.DeleteVertexArray(_probeVao);
			gl.DeleteBuffer(_quadVbo);
			gl.DeleteProgram(_barsProgram);

View on GitHub (pinned to 0418340488)

Solutions

  1. Read the appended info log — validation errors are specific ('Sampler uTex not bound to a texture unit', 'Validation differs from current state').
  2. Ensure the GL state at ValidateProgram time matches what Render will use: bind the program, set any sampler-to-texture-unit mappings, before validating.
  3. Treat ValidateProgram as advisory on some drivers (Apple, ANGLE) — if the program actually renders correctly, consider downgrading this throw to a logged warning.
  4. If the validation complains about a sampler, add the ActiveTexture + BindTexture + Uniform1(samplerLoc, unitIndex) sequence before ValidateProgram.
  5. Confirm _barsProgram is the currently bound program (UseProgram was called at line 132) before validating.

Example fix

// before
gl.ValidateProgram(_barsProgram);
gl.GetProgram(_barsProgram, ProgramPropertyARB.ValidateStatus, out int validateStatus);
if (validateStatus != (int)GLEnum.True)
    throw new Exception("ValidateProgram failed: " + gl.GetProgramInfoLog(_barsProgram));

// after — validate in the same state Render uses, log as warning if advisory-only
gl.UseProgram(_barsProgram);
gl.BindVertexArray(_barsVao);
gl.ValidateProgram(_barsProgram);
gl.GetProgram(_barsProgram, ProgramPropertyARB.ValidateStatus, out int validateStatus);
if (validateStatus != (int)GLEnum.True)
{
    var log = gl.GetProgramInfoLog(_barsProgram);
    // Some drivers (ANGLE/Apple) flag advisory issues; keep rendering if the log is non-fatal.
    System.Diagnostics.Debug.WriteLine($"ValidateProgram advisory: {log}");
}
Defensive patterns

Strategy: validation

Validate before calling

// Validate in the same state Render will use, before checking
gl.UseProgram(_barsProgram);
gl.BindVertexArray(_barsVao);
gl.ValidateProgram(_barsProgram);
gl.GetProgram(_barsProgram, ProgramPropertyARB.ValidateStatus, out int validateStatus);
// Treat as advisory on drivers known to over-flag (ANGLE, Apple)

Try / catch

try { /* ValidateProgram check */ }
catch (Exception ex) when (ex.Message.Contains("ValidateProgram failed"))
{
    // Non-fatal: validation is advisory on many drivers
    App.MainWindow?.LogError($"ValidateProgram advisory: {ex.Message}");
}

Prevention

When it happens

Trigger: After gl.ValidateProgram(_barsProgram) and gl.GetProgram(ValidateStatus, out validateStatus), validateStatus != (int)GLEnum.True (lines 153-157). The info log is appended.

Common situations: ValidateProgram runs against the current state — at this Init point no sampler textures are bound (uWave is a float array, uPalette is a vec3 array, so no samplers in _barsProgram, which is good), but if a sampler-type uniform existed without a bound texture unit the validation would fail; the current VAO/program state at validation time differs from render time; on some drivers ValidateProgram is stricter than actual execution and flags benign issues; the program was linked but with unresolved samplers.

Related errors


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