{"record":{"id":"623259c85e6a7db8","repo":"BabylonJS/Babylon.js","slug":"unable-to-create-dummy-framebuffer","errorCode":null,"errorMessage":"Unable to create dummy framebuffer","messagePattern":"Unable to create dummy framebuffer","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/dev/core/src/Engines/Extensions/engine.readTexture.pure.ts","lineNumber":42,"sourceCode":"        width: number,\r\n        height: number,\r\n        faceIndex = -1,\r\n        level = 0,\r\n        buffer: Nullable<ArrayBufferView> = null,\r\n        flushRenderer = true,\r\n        noDataConversion = false,\r\n        x = 0,\r\n        y = 0\r\n    ): ArrayBufferView {\r\n        const gl = this._gl;\r\n        if (!gl) {\r\n            throw new Error(\"Engine does not have gl rendering context.\");\r\n        }\r\n        if (!this._dummyFramebuffer) {\r\n            const dummy = gl.createFramebuffer();\r\n\r\n            if (!dummy) {\r\n                throw new Error(\"Unable to create dummy framebuffer\");\r\n            }\r\n\r\n            this._dummyFramebuffer = dummy;\r\n        }\r\n        gl.bindFramebuffer(gl.FRAMEBUFFER, this._dummyFramebuffer);\r\n\r\n        if (faceIndex > -1 && (texture.is2DArray || texture.is3D)) {\r\n            gl.framebufferTextureLayer(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, texture._hardwareTexture?.underlyingResource, level, faceIndex);\r\n        } else if (faceIndex > -1) {\r\n            gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_CUBE_MAP_POSITIVE_X + faceIndex, texture._hardwareTexture?.underlyingResource, level);\r\n        } else {\r\n            gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, texture._hardwareTexture?.underlyingResource, level);\r\n        }\r\n\r\n        let readType = texture.type !== undefined ? this._getWebGLTextureType(texture.type) : gl.UNSIGNED_BYTE;\r\n\r\n        if (!noDataConversion) {\r\n            switch (readType) {\r","sourceCodeStart":24,"sourceCodeEnd":60,"githubUrl":"https://github.com/BabylonJS/Babylon.js/blob/0592b347b8a4ee0236089ea86a749cacfdb266d8/packages/dev/core/src/Engines/Extensions/engine.readTexture.pure.ts#L24-L60","documentation":"readTexture uses a lazily-created dummy framebuffer (_dummyFramebuffer) to perform GPU-side pixel reads. If gl.createFramebuffer() returns null when first allocating this helper, this error is thrown. Like the other framebuffer errors, it points to driver/context-level allocation failure, not a usage error.","triggerScenarios":"First call to engine.readPixels/readTexture when gl.createFramebuffer() for the dummy framebuffer returns null — context lost, driver exhaustion, or non-compliant GL implementation.","commonSituations":"Context loss between engine creation and the first readPixels call; mobile devices under memory pressure; browsers with many live WebGL contexts; buggy drivers returning null from createFramebuffer.","solutions":["Verify context is alive (listen for webglcontextlost) and re-create engine if lost","Retry the readPixels call after context restore","Reduce GPU memory pressure (dispose unused textures/render targets)","Update GPU drivers/browser","Catch and fall back to reading pixels without the GPU path (e.g. sync texture data with noDataConversion/data source)"],"exampleFix":"// before\nconst data = engine.readPixels(texture);\n// after\ntry {\n  const data = engine.readPixels(texture);\n} catch (e) {\n  // fall back: read from CPU-side texture buffer if available\n  const data = texture._bufferSource;\n}","handlingStrategy":"try-catch","validationCode":"function canReadTexture(engine) {\n  return !engine.isDisposed && !!(engine as any)._gl;\n}","typeGuard":"function hasGlContext(engine): boolean {\n  return !engine.isDisposed && !!(engine as any)._gl;\n}","tryCatchPattern":"let data: ArrayBufferView | null = null;\ntry {\n  data = engine.readPixels(texture);\n} catch (e) {\n  if (String(e?.message).includes('dummy framebuffer')) {\n    data = texture._bufferSource ?? null; // CPU-side fallback\n  } else { throw e; }\n}","preventionTips":["Recover from context loss before doing GPU reads","Reduce GPU memory pressure before large readbacks","Retry readPixels after webglcontextrestored","Keep the engine alive while reads are in flight","Update drivers on problem devices"],"tags":["webgl","framebuffer","readpixels","context-loss"],"backgroundTag":"webgl-framebuffer-creation-failed","analyzedSha":"0592b347b8a4ee0236089ea86a749cacfdb266d8","analyzedAt":"2026-08-30T15:11:20.442Z","schemaVersion":2},"datasetVersion":"2026-08-30T18:17:15.746Z"}