BabylonJS/Babylon.js · error

_releaseTexture: Trying to release a texture from a non exis

Error message

_releaseTexture: Trying to release a texture from a non existing pool ${textureOptionsHash}!

What it means

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.

Source

Thrown at packages/dev/smartFilters/src/runtime/renderTargetGenerator.ts:160

            refCountedTexture = {
                texture: this._createTexture(runtime, smartFilter, textureOptions),
                refCount: 0,
            };
            refCountedTextures.add(refCountedTexture);
            this._numTargetsCreated++;
        }

        return refCountedTexture;
    }

    private _releaseTexture(texture: ThinTexture, textureOptionsHash: string) {
        if (!this._optimize) {
            return;
        }

        const refCountedTextures = this._renderTargetPool.get(textureOptionsHash);
        if (!refCountedTextures) {
            throw new Error(`_releaseTexture: Trying to release a texture from a non existing pool ${textureOptionsHash}!`);
        }

        for (const refCountedTexture of refCountedTextures) {
            if (refCountedTexture.texture === texture) {
                refCountedTexture.refCount--;
                return;
            }
        }

        throw new Error(`_releaseTexture: Can't find the texture in the pool ${textureOptionsHash}!`);
    }

    /**
     * Creates an offscreen texture to hold on the result of the block rendering.
     * @param runtime - The current runtime we create the texture for
     * @param smartFilter - The smart filter the texture is created for
     * @param textureOptions - The options to use to create the texture
     * @returns The render target texture

View on GitHub (pinned to 0592b347b8)

Solutions

  1. Check that _optimize stays consistent for the lifetime of the runtime; do not toggle optimization or re-create the generator mid-run.
  2. Ensure every texture is released exactly once — audit setOutputTextures/dispose paths for double-release calls.
  3. Verify textures being released were acquired from the same renderTargetGenerator instance that is releasing them.
  4. Re-create the runtime/renderTargetGenerator if it was disposed or its pool cleared; the pool state is unrecoverable.
  5. If reproducible, file an issue — this is normally an internal invariant violation, not user error.

Example fix

// before
runtime.setOutputTextures(oldTextures); // second release of already-released textures
// after
if (!runtime.isDisposed && !texturesReleased) {
    runtime.setOutputTextures(oldTextures);
    texturesReleased = true;
}
Defensive patterns

Strategy: try-catch

Validate before calling

function canRelease(generator, hash, texture) {
  const pool = generator._renderTargetPool;
  return !!pool?.get(hash)?.some((rct) => rct.texture === texture);
}

Type guard

function isInPool(generator, hash, texture) {
  return (generator._renderTargetPool?.get(hash) ?? []).some((r) => r.texture === texture);
}

Try / catch

try {
  runtime.setOutputTextures(textures);
} catch (e) {
  if (String(e.message).includes('_releaseTexture: Trying to release a texture from a non existing pool')) {
    // pool bookkeeping corrupted: rebuild the runtime/generator
    runtime.dispose();
    runtime = rebuildRuntime();
  } else { throw e; }
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


AI-assisted analysis of BabylonJS/Babylon.js@0592b347b8 (2026-08-30). Data as JSON: /api/errors/082c79f3f6338ce0. Report an issue: GitHub.