{"record":{"id":"6dd046181c4f0947","repo":"phaserjs/phaser","slug":"framebuffer-status","errorCode":null,"errorMessage":"Framebuffer status: ","messagePattern":"Framebuffer status: ","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"src/renderer/webgl/wrappers/WebGLFramebufferWrapper.js","lineNumber":256,"sourceCode":"            attachment = this.attachments[i];\n            var attachmentPoint = attachment.attachmentPoint;\n            var texture = attachment.texture;\n\n            if (texture)\n            {\n                texture.isRenderTexture = true;\n                gl.framebufferTexture2D(gl.FRAMEBUFFER, attachmentPoint, gl.TEXTURE_2D, texture.webGLTexture, 0);\n            }\n            else\n            {\n                // Check for completeness.\n                // We must do this after the color attachments are created,\n                // or the framebuffer will be incomplete and cannot accept\n                // a renderbuffer.\n                var complete = gl.checkFramebufferStatus(gl.FRAMEBUFFER);\n                if (complete !== gl.FRAMEBUFFER_COMPLETE)\n                {\n                    throw new Error('Framebuffer status: ' + (errors[complete] || complete));\n                }\n\n                var renderbuffer = gl.createRenderbuffer();\n                glWrapper.updateBindingsRenderbuffer({\n                    bindings:\n                    {\n                        renderbuffer: renderbuffer\n                    }\n                });\n                gl.renderbufferStorage(gl.RENDERBUFFER, attachment.internalFormat, this.width, this.height);\n                gl.framebufferRenderbuffer(gl.FRAMEBUFFER, attachmentPoint, gl.RENDERBUFFER, renderbuffer);\n\n                // We could check for completeness again here,\n                // but the invocations were checked during development,\n                // and the renderbuffer is free of error.\n\n                attachment.renderbuffer = renderbuffer;\n            }","sourceCodeStart":238,"sourceCodeEnd":274,"githubUrl":"https://github.com/phaserjs/phaser/blob/41be1e462bc600064e498cba370bfa8c5c055a22/src/renderer/webgl/wrappers/WebGLFramebufferWrapper.js#L238-L274","documentation":"Thrown by WebGLFramebufferWrapper when gl.checkFramebufferStatus returns anything other than FRAMEBUFFER_COMPLETE while attaching a depth/stencil renderbuffer. The 'errors' map translates the GL status code to a human name (e.g. INCOMPLETE_ATTACHMENT) and the raw numeric is appended as fallback.","triggerScenarios":"Requesting addDepthBuffer/addStencilBuffer with an unsupported internalFormat combination, zero-sized attachments, missing color attachments when depth is requested, unsupported texture formats for the context (WebGL1 vs WebGL2), or attaching a renderbuffer with mismatched dimensions.","commonSituations":"Enabling depth + stencil on a context/profile that does not expose DEPTH_STENCIL24_8; creating a framebuffer with non-power-of-two textures on WebGL1; passing incompatible internalFormat values; depth buffer dimensions out of sync with color after a resize; driver/GPU blacklists returning INCOMPLETE.","solutions":["Read the appended status name/number and cross-reference the WebGL framebuffer completeness table for the exact cause.","Ensure color attachments exist before requesting depth/stencil (the wrapper attaches depth after color).","Match renderbuffer internalFormat to the context (use DEPTH_STENCIL / gl.DEPTH24_STENCIL8 on WebGL2).","Verify attachment dimensions are non-zero and equal across all attachments.","Fall back to a simpler framebuffer (depth only, or color only) if the combination is unsupported on the target GPU."],"exampleFix":"// before\nnew WebGLFramebufferWrapper(renderer, {\n  addDepthBuffer: true,\n  addStencilBuffer: true\n  // no color attachments -> incomplete\n});\n\n// after\nnew WebGLFramebufferWrapper(renderer, {\n  colorAttachments: [colorTex],\n  addDepthBuffer: true,\n  addStencilBuffer: true\n});","handlingStrategy":"try-catch","validationCode":"function checkFBOComplete(gl) {\n  const status = gl.checkFramebufferStatus(gl.FRAMEBUFFER);\n  return status === gl.FRAMEBUFFER_COMPLETE;\n}","typeGuard":null,"tryCatchPattern":"try { fb = new WebGLFramebufferWrapper(renderer, cfg); } catch (e) { if (/Framebuffer status/.test(e.message)) { console.error('FBO incomplete:', e.message); /* simplify cfg: drop stencil or change format */ } else throw e; }","preventionTips":["Provide color attachments before requesting depth/stencil.","Use formats known to be supported on the target context version.","Keep attachment sizes equal and non-zero."],"tags":["renderer","webgl","framebuffer","webgl-wrapper","phaser4"],"backgroundTag":null,"analyzedSha":"41be1e462bc600064e498cba370bfa8c5c055a22","analyzedAt":"2026-08-13T04:23:39.729Z","schemaVersion":2},"datasetVersion":"2026-08-13T09:17:06.757Z"}