BabylonJS/Babylon.js · error

GaussianSplattingDownloadManager has been disposed.

Error message

GaussianSplattingDownloadManager has been disposed.

What it means

The GaussianSplattingDownloadManager coordinates shared/pending SPLAT file downloads and can be disposed via its dispose() method. Once disposed, loadFileAsync refuses all new work with this error. It signals use-after-dispose: the manager's internal state (pending tasks, abort controllers) has been torn down and cannot accept downloads.

Source

Thrown at packages/dev/loaders/src/SPLAT/gaussianSplattingDownloadManager.ts:99

    }

    /**
     * Whether there are no downloads queued or in flight.
     */
    public get isIdle(): boolean {
        return this._pending.size === 0;
    }

    /**
     * Downloads a file as an `ArrayBuffer`, queued behind the concurrency cap and retried on failure.
     * Concurrent requests for the same URL resolve from a single shared download.
     * @param url the file URL to download
     * @param groupId optional group tag so related downloads can be cancelled together via {@link cancelGroup}
     * @returns a promise resolving with the downloaded bytes
     */
    public async loadFileAsync(url: string, groupId?: DownloadGroupId): Promise<ArrayBuffer> {
        if (this._disposed) {
            throw new Error("GaussianSplattingDownloadManager has been disposed.");
        }
        const existing = this._pending.get(url);
        if (existing) {
            return await existing.promise;
        }
        const task: IDownloadTask = {
            url,
            groupId,
            settled: false,
            cancelled: false,
            started: false,
            slotReleased: false,
        } as IDownloadTask;
        task.promise = new Promise<ArrayBuffer>((resolve, reject) => {
            task.resolve = resolve;
            task.reject = reject;
        });
        this._pending.set(url, task);

View on GitHub (pinned to 0592b347b8)

Solutions

  1. Create a new GaussianSplattingDownloadManager instance after disposing the previous one.
  2. Restructure code so dispose() is only called after all loadFileAsync promises settle.
  3. Guard call sites with a disposed check or a flag reset when reinitializing the scene.
  4. If using framework lifecycle hooks, bind the manager's lifetime to the engine/scene instead of a component that unmounts early.

Example fix

// before
manager.dispose();
await manager.loadFileAsync(url); // throws
// after
manager.dispose();
manager = new GaussianSplattingDownloadManager();
await manager.loadFileAsync(url);
Defensive patterns

Strategy: try-catch

Validate before calling

let manager: GaussianSplattingDownloadManager | null = getManager();
if (!manager) {
  manager = new GaussianSplattingDownloadManager(); // recreate if disposed
}

Type guard

function isManagerUsable(m: GaussianSplattingDownloadManager | null): m is GaussianSplattingDownloadManager {
  return m !== null && !m.isDisposed; // track via your own flag if not exposed
}

Try / catch

try {
  const data = await manager.loadFileAsync(url, groupId);
} catch (e) {
  if (String(e.message).includes("has been disposed")) {
    manager = new GaussianSplattingDownloadManager();
    return manager.loadFileAsync(url, groupId);
  }
  throw e;
}

Prevention

When it happens

Trigger: Calling loadFileAsync after GaussianSplattingDownloadManager.dispose() was invoked, e.g. loading another splat file with the same manager instance after a scene/mesh was disposed.

Common situations: Reusing a loader/manager across scene reloads; disposing a GaussianSplatting mesh then attempting to stream another file through the same manager; race between an async load and scene disposal.

Related errors


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