{"record":{"id":"a0f01b7848818f39","repo":"BabylonJS/Babylon.js","slug":"framegraphrendertarget-rendertargetwrapper-failed","errorCode":null,"errorMessage":"FrameGraphRenderTarget.renderTargetWrapper: Failed to get texture from handle. handle: ${handle}, name: ${this.name}, index: ${i}, renderTargets: ${this._renderTargets}","messagePattern":"FrameGraphRenderTarget\\.renderTargetWrapper: Failed to get texture from handle\\. handle: (.+?), name: (.+?), index: (.+?), renderTargets: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/dev/core/src/FrameGraph/frameGraphRenderTarget.ts","lineNumber":60,"sourceCode":"\r\n            const textureDescription = this._textureManager.getTextureDescription(textureHandle);\r\n\r\n            const creationOptionsForTexture: IMultiRenderTargetOptions = {\r\n                textureCount: this._renderTargets?.length ?? 0,\r\n                generateDepthBuffer: false,\r\n                label: this.name,\r\n                samples: textureDescription.options.samples ?? 1,\r\n                dontCreateTextures: true,\r\n            };\r\n\r\n            this._renderTargetWrapper = engine.createMultipleRenderTarget(textureDescription.size, creationOptionsForTexture, true);\r\n\r\n            for (let i = 0; i < creationOptionsForTexture.textureCount!; i++) {\r\n                const handle = this._renderTargets![i];\r\n                const texture = this._textureManager.getTextureFromHandle(handle);\r\n\r\n                if (!texture) {\r\n                    throw new Error(\r\n                        `FrameGraphRenderTarget.renderTargetWrapper: Failed to get texture from handle. handle: ${handle}, name: ${this.name}, index: ${i}, renderTargets: ${this._renderTargets}`\r\n                    );\r\n                }\r\n\r\n                texture.incrementReferences();\r\n\r\n                this._renderTargetWrapper.setTexture(texture, i, false);\r\n            }\r\n\r\n            if (this._renderTargetDepth !== undefined) {\r\n                this._renderTargetWrapper.setDepthStencilTexture(this._textureManager.getTextureFromHandle(this._renderTargetDepth), false);\r\n            }\r\n        }\r\n\r\n        return this._renderTargetWrapper;\r\n    }\r\n\r\n    public equals(other: FrameGraphRenderTarget): boolean {\r","sourceCodeStart":42,"sourceCodeEnd":78,"githubUrl":"https://github.com/BabylonJS/Babylon.js/blob/0592b347b8a4ee0236089ea86a749cacfdb266d8/packages/dev/core/src/FrameGraph/frameGraphRenderTarget.ts#L42-L78","documentation":"When FrameGraphRenderTarget builds its renderTargetWrapper, it resolves each handle in _renderTargets via the texture manager's getTextureFromHandle. If a handle does not map to an existing texture (never created, already released/disposed, or a dangling handle), the wrapper cannot be built and it throws with full diagnostic context.","triggerScenarios":"Assigning a texture handle to a render target whose backing texture was never created or was disposed (texture manager released it), then accessing renderTarget.renderTargetWrapper; using a handle from a different FrameGraph/texture manager instance.","commonSituations":"Disposing textures while the frame graph still references them; using handles from a previous frame graph rebuild; passing an imported texture handle that was not registered with this frame graph's texture manager.","solutions":["Ensure every handle in the render target's _renderTargets was created by this frame graph's texture manager and not disposed.","Recreate the render target (or refresh its handles) after any frame graph rebuild or texture disposal.","Check texture reference counts and avoid disposing textures that tasks/render targets still depend on."],"exampleFix":"// before\nrt._renderTargets[i] = oldHandle; // texture already disposed\ntextureManager.disposeTexture(oldHandle);\nconst wrapper = rt.renderTargetWrapper; // throws\n// after\nrt._renderTargets[i] = fg.createTexture({ name: 'rt', options: { ... } });\nconst wrapper = rt.renderTargetWrapper;","handlingStrategy":"validation","validationCode":"const allValid = rt._renderTargets.every((h) => frameGraph.textureManager.getTextureFromHandle(h) !== undefined);\nif (!allValid) {\n  throw new Error('Render target references a disposed or unknown texture handle');\n}","typeGuard":null,"tryCatchPattern":"try {\n  const wrapper = rt.renderTargetWrapper;\n} catch (e) {\n  if (String(e.message).includes('Failed to get texture from handle')) {\n    // rebuild handles / recreate textures before retrying\n  } else {\n    throw e;\n  }\n}","preventionTips":["Track and dispose textures only after their owning render target and tasks are released.","Never mix texture handles between different frame graph instances."],"tags":["babylonjs","framegraph","dangling-handle","texture","lifecycle"],"backgroundTag":"texture-handle-not-resolved","analyzedSha":"0592b347b8a4ee0236089ea86a749cacfdb266d8","analyzedAt":"2026-08-30T15:11:20.442Z","schemaVersion":2},"datasetVersion":"2026-08-30T18:17:15.746Z"}