{"record":{"id":"092d28b5984f0774","repo":"unoplatform/uno","slug":"offscreen-framebuffer-is-not-complete","errorCode":null,"errorMessage":"Offscreen framebuffer is not complete","messagePattern":"Offscreen framebuffer is not complete","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"src/AddIns/Uno.WinUI.Graphics3DGL/GLCanvasElement.FrameBufferDetails.cs","lineNumber":51,"sourceCode":"\t\t\t\t\tgl.TexParameter(GLEnum.Texture2D, GLEnum.TextureMinFilter, (int)GLEnum.Linear);\n\t\t\t\t\tgl.TexParameter(GLEnum.Texture2D, GLEnum.TextureMagFilter, (int)GLEnum.Linear);\n\t\t\t\t\tgl.FramebufferTexture2D(GLEnum.Framebuffer, FramebufferAttachment.ColorAttachment0,\n\t\t\t\t\t\tGLEnum.Texture2D, _textureColorBuffer, 0);\n\t\t\t\t}\n\t\t\t\tgl.BindTexture(GLEnum.Texture2D, 0);\n\n\t\t\t\t_renderBuffer = gl.GenRenderbuffer();\n\t\t\t\tgl.BindRenderbuffer(GLEnum.Renderbuffer, _renderBuffer);\n\t\t\t\t{\n\t\t\t\t\tgl.RenderbufferStorage(GLEnum.Renderbuffer, InternalFormat.Depth24Stencil8, (uint)renderSize.Width, (uint)renderSize.Height);\n\t\t\t\t\tgl.FramebufferRenderbuffer(GLEnum.Framebuffer, GLEnum.DepthStencilAttachment,\n\t\t\t\t\t\tGLEnum.Renderbuffer, _renderBuffer);\n\t\t\t\t}\n\t\t\t\tgl.BindRenderbuffer(GLEnum.Renderbuffer, 0);\n\n\t\t\t\tif (gl.CheckFramebufferStatus(GLEnum.Framebuffer) != GLEnum.FramebufferComplete)\n\t\t\t\t{\n\t\t\t\t\tthrow new InvalidOperationException(\"Offscreen framebuffer is not complete\");\n\t\t\t\t}\n\t\t\t}\n\t\t\tgl.BindFramebuffer(GLEnum.Framebuffer, 0);\n\t\t}\n\n\t\tpublic void Dispose()\n\t\t{\n\t\t\t_gl.DeleteFramebuffer(Framebuffer);\n\t\t\t_gl.DeleteTexture(_textureColorBuffer);\n\t\t\t_gl.DeleteRenderbuffer(_renderBuffer);\n\t\t}\n\t}\n}\n","sourceCodeStart":33,"sourceCodeEnd":65,"githubUrl":"https://github.com/unoplatform/uno/blob/04183404888ea21b4e5bfa3493e8d5f15e972c3a/src/AddIns/Uno.WinUI.Graphics3DGL/GLCanvasElement.FrameBufferDetails.cs#L33-L65","documentation":"GLCanvasElement's FrameBufferDetails allocates an offscreen GL framebuffer (color texture + depth/stencil renderbuffer) for offscreen rendering, then asserts gl.CheckFramebufferStatus == FramebufferComplete. If not, it throws InvalidOperationException. GL defines several incompleteness causes (missing attachment, mismatched dimensions, unsupported internal format, unsupported sample counts, no GL context current).","triggerScenarios":"RenderSize has zero width or height; the depth/stencil InternalFormat (Depth24Stencil8) is unsupported by the GL driver; the framebuffer was bound without a current GL context; renderbuffer storage allocation silently failed on the driver.","commonSituations":"Element resized to 0x0 before first render; running on a GL driver lacking EXT_packed_depth_stencil / GL_DEPTH24_STENCIL8; context loss between framebuffer creation and the status check; running GLCanvasElement on a headless/Software GL context.","solutions":["Guard against zero/negative RenderSize before creating the framebuffer; skip rendering until a valid size is set.","Query gl.CheckFramebufferStatus's specific reason (gl.GetFramebufferAttachmentParameter / driver logs) to distinguish format vs. attachment failure.","On drivers without Depth24Stencil8, fall back to a stencil-only or depth-only renderbuffer, or skip depth/stencil if your scene doesn't need it.","Ensure a GL context is current on the calling thread when the framebuffer is built."],"exampleFix":"// before\nif (gl.CheckFramebufferStatus(GLEnum.Framebuffer) != GLEnum.FramebufferComplete)\n{\n\tthrow new InvalidOperationException(\"Offscreen framebuffer is not complete\");\n}\n\n// after\nif (RenderSize.Width <= 0 || RenderSize.Height <= 0) { return; }\nvar status = gl.CheckFramebufferStatus(GLEnum.Framebuffer);\nif (status != GLEnum.FramebufferComplete)\n{\n\tthis.Log().Error($\"Framebuffer incomplete: {status}\");\n\treturn; // skip this frame rather than crash","handlingStrategy":"validation","validationCode":"if (RenderSize.Width <= 0 || RenderSize.Height <= 0) return; // skip degenerate size","typeGuard":"static bool ValidRenderSize(Size s) => s.Width > 0 && s.Height > 0;","tryCatchPattern":"try { BuildFramebuffer(); }\ncatch (InvalidOperationException ex) when (ex.Message.Contains(\"framebuffer\")) { this.Log().Error(ex); }","preventionTips":["Never allocate the framebuffer with a zero-sized render target.","Verify GL context is current on the render thread before framebuffer ops.","Confirm the driver supports GL_DEPTH24_STENCIL8 before requiring depth/stencil."],"tags":["opengl","graphics","framebuffer","glcanvaselement","driver"],"backgroundTag":null,"analyzedSha":"04183404888ea21b4e5bfa3493e8d5f15e972c3a","analyzedAt":"2026-08-13T21:08:11.651Z","schemaVersion":2},"datasetVersion":"2026-08-14T00:17:13.853Z"}