BabylonJS/Babylon.js · critical

SmartAssetManager: Unknown manager state.

Error message

SmartAssetManager: Unknown manager state.

What it means

GetSmartAssetInternals looked up the manager in the global WeakMap of manager->internals and found nothing. Every public SmartAssetManager function funnels through this lookup, so it indicates the manager instance was not created/registered through the library's own constructor path (e.g. a hand-constructed or deserialized manager object, or one whose internals entry was never attached).

Source

Thrown at packages/dev/core/src/SmartAssets/smartAssetManager.pure.ts:555

    internal.textureKeys.clear();
    internal.reloadSources.clear();
    internal.containers.clear();
    for (const blobUrl of Array.from(internal.blobUrls.values())) {
        URL.revokeObjectURL(blobUrl);
    }
    internal.blobUrls.clear();

    manager.onChangedObservable.clear();

    if (manager.scene.metadata) {
        delete manager.scene.metadata[SMART_ASSET_MANAGER_KEY];
    }
}

function GetSmartAssetInternals(manager: SmartAssetManager): SmartAssetManagerInternals {
    const internal = GetInternalsMap().get(manager);
    if (!internal) {
        throw new Error("SmartAssetManager: Unknown manager state.");
    }
    return internal;
}

function RevokeManagedBlobUrl(internal: SmartAssetManagerInternals, key: string, replacementUrl?: string): void {
    const blobUrl = internal.blobUrls.get(key);
    if (!blobUrl || blobUrl === replacementUrl) {
        return;
    }
    URL.revokeObjectURL(blobUrl);
    internal.blobUrls.delete(key);
}

function TrackManagedBlobUrl(internal: SmartAssetManagerInternals, key: string, url: string): void {
    if (url.startsWith("blob:")) {
        internal.blobUrls.set(key, url);
    }
}

View on GitHub (pinned to 0592b347b8)

Solutions

  1. Obtain the manager via GetSmartAssetManager(scene) instead of constructing or copying SmartAssetManager instances directly.
  2. After a hot reload or test setup, re-acquire the manager from the scene rather than reusing a cached old instance.
  3. In tests, use the real factory (or the library's provided mock/internals hook) instead of a plain-object stub.
  4. Check that no code path clears the internals map (module re-evaluation) before the manager is used.

Example fix

// before
const manager = new SmartAssetManager(); // not tracked in internals WeakMap
const all = GetAllSmartAssets(scene);
// after
const manager = GetSmartAssetManager(scene); // factory-managed instance
const all = GetAllSmartAssets(scene);
Defensive patterns

Strategy: try-catch

Validate before calling

function managerIsUsable(manager: unknown): manager is SmartAssetManager {
    try {
        GetAllSmartAssets(GetSmartAssetManager(scene)); // forces internals lookup
        return true;
    } catch {
        return false;
    }
}

Type guard

function isTrackedSmartAssetManager(m: unknown): m is SmartAssetManager {
    return m instanceof SmartAssetManager && internalsWeakMapHas(m); // if internals map is exported; otherwise probe via a cheap API call in try/catch
}

Try / catch

let internal: SmartAssetManagerInternals;
try {
    internal = GetSmartAssetInternals(manager);
} catch (e) {
    if (e instanceof Error && e.message === 'SmartAssetManager: Unknown manager state.') {
        manager = GetSmartAssetManager(scene); // re-acquire factory-managed instance
        internal = GetSmartAssetInternals(manager);
    } else {
        throw e;
    }
}

Prevention

When it happens

Trigger: Calling GetSmartAssetInternals-backed APIs (GetAllSmartAssets, FindSmartAssetKeyForObject, loads, unloads) on a SmartAssetManager that was created outside the library's factory (e.g. Object.create(SmartAssetManager.prototype), structuredClone, or a stale instance across a hot reload that lost the WeakMap binding).

Common situations: Hot module reload recreating the WeakMap while an old manager instance survives; mocking or stubbing SmartAssetManager in tests with a plain object; restoring a manager from a serialized snapshot instead of going through GetSmartAssetManager(scene).

Related errors


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