{"record":{"id":"082c79f3f6338ce0","repo":"BabylonJS/Babylon.js","slug":"releasetexture-trying-to-release-a-texture-from","errorCode":null,"errorMessage":"_releaseTexture: Trying to release a texture from a non existing pool ${textureOptionsHash}!","messagePattern":"_releaseTexture: Trying to release a texture from a non existing pool (.+?)!","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/dev/smartFilters/src/runtime/renderTargetGenerator.ts","lineNumber":160,"sourceCode":"            refCountedTexture = {\r\n                texture: this._createTexture(runtime, smartFilter, textureOptions),\r\n                refCount: 0,\r\n            };\r\n            refCountedTextures.add(refCountedTexture);\r\n            this._numTargetsCreated++;\r\n        }\r\n\r\n        return refCountedTexture;\r\n    }\r\n\r\n    private _releaseTexture(texture: ThinTexture, textureOptionsHash: string) {\r\n        if (!this._optimize) {\r\n            return;\r\n        }\r\n\r\n        const refCountedTextures = this._renderTargetPool.get(textureOptionsHash);\r\n        if (!refCountedTextures) {\r\n            throw new Error(`_releaseTexture: Trying to release a texture from a non existing pool ${textureOptionsHash}!`);\r\n        }\r\n\r\n        for (const refCountedTexture of refCountedTextures) {\r\n            if (refCountedTexture.texture === texture) {\r\n                refCountedTexture.refCount--;\r\n                return;\r\n            }\r\n        }\r\n\r\n        throw new Error(`_releaseTexture: Can't find the texture in the pool ${textureOptionsHash}!`);\r\n    }\r\n\r\n    /**\r\n     * Creates an offscreen texture to hold on the result of the block rendering.\r\n     * @param runtime - The current runtime we create the texture for\r\n     * @param smartFilter - The smart filter the texture is created for\r\n     * @param textureOptions - The options to use to create the texture\r\n     * @returns The render target texture\r","sourceCodeStart":142,"sourceCodeEnd":178,"githubUrl":"https://github.com/BabylonJS/Babylon.js/blob/0592b347b8a4ee0236089ea86a749cacfdb266d8/packages/dev/smartFilters/src/runtime/renderTargetGenerator.ts#L142-L178","documentation":"The Smart Filter runtime maintains a pool of reusable render target textures keyed by a hash of their texture options. _releaseTexture decrements the ref count of a texture returned to the pool; this error is thrown when no pool entry exists for the given textureOptionsHash, meaning the runtime is asked to release a texture that was never created by (or has already been fully removed from) the render target pool. It guards only when _optimize is enabled, so it indicates internal bookkeeping corruption or a mismatched release call.","triggerScenarios":"setOutputTextures (or other runtime teardown paths) calls _releaseTexture with a hash that has no entry in _renderTargetPool — e.g. releasing the same texture twice (double-release), releasing a texture created while _optimize was false, or an already-drained pool entry that was deleted after its ref count hit zero.","commonSituations":"Rendering the same Smart Filter runtime twice with differing optimization settings, re-using a runtime/disposed texture objects across runs, calling dispose or setOutputTextures twice on the same frame graph, or framework-level bugs where the pool was cleared between acquire and release.","solutions":["Check that _optimize stays consistent for the lifetime of the runtime; do not toggle optimization or re-create the generator mid-run.","Ensure every texture is released exactly once — audit setOutputTextures/dispose paths for double-release calls.","Verify textures being released were acquired from the same renderTargetGenerator instance that is releasing them.","Re-create the runtime/renderTargetGenerator if it was disposed or its pool cleared; the pool state is unrecoverable.","If reproducible, file an issue — this is normally an internal invariant violation, not user error."],"exampleFix":"// before\nruntime.setOutputTextures(oldTextures); // second release of already-released textures\n// after\nif (!runtime.isDisposed && !texturesReleased) {\n    runtime.setOutputTextures(oldTextures);\n    texturesReleased = true;\n}","handlingStrategy":"try-catch","validationCode":"function canRelease(generator, hash, texture) {\n  const pool = generator._renderTargetPool;\n  return !!pool?.get(hash)?.some((rct) => rct.texture === texture);\n}","typeGuard":"function isInPool(generator, hash, texture) {\n  return (generator._renderTargetPool?.get(hash) ?? []).some((r) => r.texture === texture);\n}","tryCatchPattern":"try {\n  runtime.setOutputTextures(textures);\n} catch (e) {\n  if (String(e.message).includes('_releaseTexture: Trying to release a texture from a non existing pool')) {\n    // pool bookkeeping corrupted: rebuild the runtime/generator\n    runtime.dispose();\n    runtime = rebuildRuntime();\n  } else { throw e; }\n}","preventionTips":["Release each texture exactly once; track released textures in a Set.","Keep _optimize setting constant for the generator's lifetime.","Only pass textures obtained from the same generator instance back to it.","Never release textures from a disposed or cleared runtime.","Treat pool errors as internal bugs: log hash + texture identity for bug reports."],"tags":["smart-filters","render-target-pool","texture-lifecycle","internal-state"],"backgroundTag":"texture-double-release","analyzedSha":"0592b347b8a4ee0236089ea86a749cacfdb266d8","analyzedAt":"2026-08-30T15:11:20.442Z","schemaVersion":2},"datasetVersion":"2026-08-30T18:17:15.746Z"}