{"record":{"id":"bfa6b134aea3aff2","repo":"BabylonJS/Babylon.js","slug":"smartassetmanager-unknown-manager-state","errorCode":null,"errorMessage":"SmartAssetManager: Unknown manager state.","messagePattern":"SmartAssetManager: Unknown manager state\\.","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"packages/dev/core/src/SmartAssets/smartAssetManager.pure.ts","lineNumber":555,"sourceCode":"    internal.textureKeys.clear();\n    internal.reloadSources.clear();\n    internal.containers.clear();\n    for (const blobUrl of Array.from(internal.blobUrls.values())) {\n        URL.revokeObjectURL(blobUrl);\n    }\n    internal.blobUrls.clear();\n\n    manager.onChangedObservable.clear();\n\n    if (manager.scene.metadata) {\n        delete manager.scene.metadata[SMART_ASSET_MANAGER_KEY];\n    }\n}\n\nfunction GetSmartAssetInternals(manager: SmartAssetManager): SmartAssetManagerInternals {\n    const internal = GetInternalsMap().get(manager);\n    if (!internal) {\n        throw new Error(\"SmartAssetManager: Unknown manager state.\");\n    }\n    return internal;\n}\n\nfunction RevokeManagedBlobUrl(internal: SmartAssetManagerInternals, key: string, replacementUrl?: string): void {\n    const blobUrl = internal.blobUrls.get(key);\n    if (!blobUrl || blobUrl === replacementUrl) {\n        return;\n    }\n    URL.revokeObjectURL(blobUrl);\n    internal.blobUrls.delete(key);\n}\n\nfunction TrackManagedBlobUrl(internal: SmartAssetManagerInternals, key: string, url: string): void {\n    if (url.startsWith(\"blob:\")) {\n        internal.blobUrls.set(key, url);\n    }\n}","sourceCodeStart":537,"sourceCodeEnd":573,"githubUrl":"https://github.com/BabylonJS/Babylon.js/blob/0592b347b8a4ee0236089ea86a749cacfdb266d8/packages/dev/core/src/SmartAssets/smartAssetManager.pure.ts#L537-L573","documentation":"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).","triggerScenarios":"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).","commonSituations":"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).","solutions":["Obtain the manager via GetSmartAssetManager(scene) instead of constructing or copying SmartAssetManager instances directly.","After a hot reload or test setup, re-acquire the manager from the scene rather than reusing a cached old instance.","In tests, use the real factory (or the library's provided mock/internals hook) instead of a plain-object stub.","Check that no code path clears the internals map (module re-evaluation) before the manager is used."],"exampleFix":"// before\nconst manager = new SmartAssetManager(); // not tracked in internals WeakMap\nconst all = GetAllSmartAssets(scene);\n// after\nconst manager = GetSmartAssetManager(scene); // factory-managed instance\nconst all = GetAllSmartAssets(scene);","handlingStrategy":"try-catch","validationCode":"function managerIsUsable(manager: unknown): manager is SmartAssetManager {\n    try {\n        GetAllSmartAssets(GetSmartAssetManager(scene)); // forces internals lookup\n        return true;\n    } catch {\n        return false;\n    }\n}","typeGuard":"function isTrackedSmartAssetManager(m: unknown): m is SmartAssetManager {\n    return m instanceof SmartAssetManager && internalsWeakMapHas(m); // if internals map is exported; otherwise probe via a cheap API call in try/catch\n}","tryCatchPattern":"let internal: SmartAssetManagerInternals;\ntry {\n    internal = GetSmartAssetInternals(manager);\n} catch (e) {\n    if (e instanceof Error && e.message === 'SmartAssetManager: Unknown manager state.') {\n        manager = GetSmartAssetManager(scene); // re-acquire factory-managed instance\n        internal = GetSmartAssetInternals(manager);\n    } else {\n        throw e;\n    }\n}","preventionTips":["Only obtain managers via GetSmartAssetManager(scene); never construct or clone SmartAssetManager manually.","After hot module reloads, re-acquire the manager instead of caching stale instances.","In tests, use the library's factory or provided test helpers, not plain-object stubs.","Avoid structuredClone/postMessage of manager instances — WeakMap-tracked internals do not survive.","Wrap manager acquisition once at app startup and share that single instance."],"tags":["smart-assets","state-corruption","internal-state","babylon"],"backgroundTag":"unknown-manager-state","analyzedSha":"0592b347b8a4ee0236089ea86a749cacfdb266d8","analyzedAt":"2026-08-30T15:11:20.442Z","schemaVersion":2},"datasetVersion":"2026-08-30T18:17:15.746Z"}