{"record":{"id":"5232e77dbce6fa31","repo":"unoplatform/uno","slug":"gl-error-at-end-of-init-0x-int-err-x-5232e7","errorCode":null,"errorMessage":"GL error at end of Init: 0x{(int)err:x}","messagePattern":"GL error at end of Init: 0x(.+?)","errorType":"exception","errorClass":"Exception","httpStatus":null,"severity":"error","filePath":"src/SamplesApp/SamplesApp.Samples/Windows_UI_Composition/QuerySyncGlCanvasElement.cs","lineNumber":166,"sourceCode":"\t\t\t}\n\t\t\tif (!foundWave)\n\t\t\t{\n\t\t\t\tthrow new Exception($\"GetActiveUniform did not report uWave[{BarCount}] (saw {activeUniforms} active uniforms)\");\n\t\t\t}\n\t\t\tgl.ValidateProgram(_barsProgram);\n\t\t\tgl.GetProgram(_barsProgram, ProgramPropertyARB.ValidateStatus, out int validateStatus);\n\t\t\tif (validateStatus != (int)GLEnum.True)\n\t\t\t{\n\t\t\t\tthrow new Exception(\"ValidateProgram failed: \" + gl.GetProgramInfoLog(_barsProgram));\n\t\t\t}\n\n\t\t\t_query = gl.GenQuery();\n\n\t\t\t// Init must finish error-clean; surface anything the calls above raised.\n\t\t\tvar err = gl.GetError();\n\t\t\tif (err != GLEnum.NoError)\n\t\t\t{\n\t\t\t\tthrow new Exception($\"GL error at end of Init: 0x{(int)err:x}\");\n\t\t\t}\n\t\t}\n\n\t\tprotected override void OnDestroy(GL gl)\n\t\t{\n\t\t\tgl.DeleteVertexArray(_barsVao);\n\t\t\tgl.DeleteVertexArray(_probeVao);\n\t\t\tgl.DeleteBuffer(_quadVbo);\n\t\t\tgl.DeleteProgram(_barsProgram);\n\t\t\tgl.DeleteProgram(_probeProgram);\n\t\t\tgl.DeleteQuery(_query);\n\t\t\tif (_frameSync != 0)\n\t\t\t{\n\t\t\t\tgl.DeleteSync(_frameSync);\n\t\t\t\t_frameSync = 0;\n\t\t\t}\n\t\t}\n","sourceCodeStart":148,"sourceCodeEnd":184,"githubUrl":"https://github.com/unoplatform/uno/blob/04183404888ea21b4e5bfa3493e8d5f15e972c3a/src/SamplesApp/SamplesApp.Samples/Windows_UI_Composition/QuerySyncGlCanvasElement.cs#L148-L184","documentation":"At the end of Init, QuerySyncGlCanvasElement calls gl.GetError() and asserts it returns NO_ERROR. This is a sweep check: any GL call above (Uniform, GetUniform, GetProgram, GetActiveUniform, ValidateProgram, GenQuery) that raised an error leaves the error flag set, and this throw surfaces the accumulated code rather than letting the sample run with silently-broken state.","triggerScenarios":"After all Init GL setup, gl.GetError() returns something other than GLEnum.NoError (lines 163-166). The hex code (e.g. 0x502 invalid_operation) is included in the message.","commonSituations":"A preceding call set the error flag — common culprits: GetUniformLocation returned -1 and a subsequent Uniform* on -1 set invalid_operation; GenQuery returned 0 (context lacks query support) and a later query op set invalid_operation; ValidateProgram on a program that is not the current program object set an error; introspection GetActiveUniform with an out-of-range index set invalid_enum. Note GetError returns only the first of potentially multiple queued errors.","solutions":["Move the gl.GetError() check earlier and interleave it after each major GL call group to localize which call raised the error (GetError drains the queue one at a time).","Decode the hex code: 0x500 invalid_enum, 0x501 invalid_value, 0x502 invalid_operation, 0x503 stack_overflow, 0x504 stack_underflow, 0x505 out_of_memory, 0x506 invalid_framebuffer_operation.","Verify all uniform locations are non-negative before calling Uniform*, all program/query objects are non-zero before use, and the program is bound before introspection that requires it.","Loop GetError until it returns NoError to drain all queued errors, capturing each — a single GetError only reports the first.","On WebGL2/GLES where GetError is asynchronous, call gl.Flush() before the sweep so pending errors are surfaced."],"exampleFix":"// before\nvar err = gl.GetError();\nif (err != GLEnum.NoError)\n    throw new Exception($\"GL error at end of Init: 0x{(int)err:x}\");\n\n// after — drain and label each erroring call group\nstatic void AssertClean(GL gl, string label)\n{\n    var errs = new List<GLEnum>();\n    GLEnum e;\n    while ((e = gl.GetError()) != GLEnum.NoError) errs.Add(e);\n    if (errs.Count > 0)\n        throw new Exception($\"GL error after {label}: {string.Join(\", \", errs.Select(e => $\"0x{(int)e:x}\"))}\");\n}\n// sprinkle AssertClean(gl, \"uniform upload\"), AssertClean(gl, \"introspection\"), etc.","handlingStrategy":"validation","validationCode":"// Drain all queued errors at each step, not just at the end\nstatic void AssertClean(GL gl, string label)\n{\n    var errs = new List<GLEnum>();\n    GLEnum e;\n    while ((e = gl.GetError()) != GLEnum.NoError) errs.Add(e);\n    if (errs.Count > 0)\n        throw new Exception($\"GL error after {label}: {string.Join(\", \", errs.Select(x => $\"0x{(int)x:x}\"))}\");\n}\nAssertClean(gl, \"uniform upload\");\nAssertClean(gl, \"introspection\");\nAssertClean(gl, \"validate\");","typeGuard":null,"tryCatchPattern":"try { /* Init */ AssertClean(gl, \"end of Init\"); }\ncatch (Exception ex) when (ex.Message.Contains(\"GL error at end of Init\"))\n{\n    App.MainWindow?.LogError(ex.Message);\n    _initFailed = true;\n}","preventionTips":["Interleave GetError checks after each major GL call group to localize the offender.","Drain the error queue in a loop (a single GetError only reports the first).","Verify uniform locations are non-negative before Uniform* calls.","Verify program/query objects are non-zero before use.","Call gl.Flush() before the sweep on GLES/WebGL where errors are asynchronous."],"tags":["opengl","silk-net","get-error","diagnostics","gl-state","error-sweep"],"backgroundTag":null,"analyzedSha":"04183404888ea21b4e5bfa3493e8d5f15e972c3a","analyzedAt":"2026-08-13T21:08:11.651Z","schemaVersion":2},"datasetVersion":"2026-08-14T00:17:13.853Z"}