BabylonJS/Babylon.js · error
SmartAssetManager: Key "${key}" is not registered. Provide a
Error message
SmartAssetManager: Key "${key}" is not registered. Provide a URL to auto-register. What it means
LoadSmartAssetAsync was called with a key that has no URL registered in the SmartAssetManager's internal registry, and no url argument was supplied to auto-register it. The manager only serves assets whose key->URL mapping was previously added via RegisterSmartAsset (or a prior load with a url). Without a resolved URL it cannot fetch anything, so it throws rather than silently returning an empty container.
Source
Thrown at packages/dev/core/src/SmartAssets/smartAssetManager.pure.ts:245
* @param url - Optional URL. If provided, the key is registered first.
* @param options - Optional loader hints and metadata for this asset.
* @returns A promise resolving to the loaded AssetContainer.
*/
export async function LoadSmartAssetAsync(scene: Scene, key: string, url?: string, options?: SmartAssetLoadOptions): Promise<AssetContainer> {
const manager = GetSmartAssetManager(scene);
const internal = GetSmartAssetInternals(manager);
const previousUrl = internal.urls.get(key);
const { reloadSource, ...registrationOptions } = options ?? {};
if (url) {
RegisterSmartAsset(scene, key, url, registrationOptions);
}
if (reloadSource) {
internal.reloadSources.set(key, reloadSource);
}
const resolvedUrl = internal.urls.get(key);
if (!resolvedUrl) {
throw new Error(`SmartAssetManager: Key "${key}" is not registered. Provide a URL to auto-register.`);
}
const existing = internal.containers.get(key);
if (existing) {
if (url && url !== previousUrl) {
// URL changed — drop the stale container before fetching the new one
// so callers don't get a surprise cached return for an updated URL.
await UnloadSmartAssetAsync(scene, key);
} else {
return existing;
}
}
return await LoadSmartAssetSceneFileAsync(manager, key, resolvedUrl, internal.options.get(key)?.extension);
}
/**
* Loads all registered assets concurrently.View on GitHub (pinned to 0592b347b8)
Solutions
- Pass the URL so the key auto-registers: LoadSmartAssetAsync(scene, key, url).
- Check the key exists before loading with GetAllSmartAssets(scene).has(key); register it first via RegisterSmartAsset if missing.
- Verify the key string against the registered keys (typos/renames are the most common cause).
- Ensure you are using the SmartAssetManager for the correct Scene — registrations are per-scene and will not be found on a different scene's manager.
- If the key was intentionally unloaded, re-register it before the next load/reload call.
Example fix
// before
const container = await LoadSmartAssetAsync(scene, "player-model");
// after
if (!GetAllSmartAssets(scene).has("player-model")) {
RegisterSmartAsset(scene, "player-model", "https://cdn.example.com/player.glb");
}
const container = await LoadSmartAssetAsync(scene, "player-model"); Defensive patterns
Strategy: validation
Validate before calling
function ensureSmartAssetRegistered(scene: Scene, key: string): boolean {
return GetAllSmartAssets(scene).has(key);
}
// call site:
if (!ensureSmartAssetRegistered(scene, key)) {
RegisterSmartAsset(scene, key, url);
}
const container = await LoadSmartAssetAsync(scene, key); Try / catch
try {
container = await LoadSmartAssetAsync(scene, key);
} catch (e) {
if (e instanceof Error && e.message.includes('is not registered')) {
container = await LoadSmartAssetAsync(scene, key, fallbackUrls[key]);
} else {
throw e;
}
} Prevention
- Always call RegisterSmartAsset (or pass a url to the load call) before loading a key.
- Check GetAllSmartAssets(scene).has(key) before any load or reload.
- Centralize key names in a constants module to avoid typos and renames drifting.
- Remember UnloadSmartAssetAsync deletes the registration — re-register after unloading.
- Keep registration and load on the same Scene instance.
When it happens
Trigger: LoadSmartAssetAsync(scene, key) with a key never registered via RegisterSmartAsset; calling with a key that was just removed by UnloadSmartAssetAsync (which deletes urls/options/containers for the key, see lines 206-210); a typo'd or renamed key; calling load before project deserialization populated the registry (e.g. DeserializeSmartAssetMap result not applied); loading on a different scene's manager than the one where assets were registered.
Common situations: Loading a saved project where the asset map failed to deserialize or was loaded into another scene; renaming an asset key in one place but not the other; calling ReloadSmartAssetAsync after the key was unloaded; hand-written load calls using keys from an older project file whose registrations were dropped.
Related errors
- SmartAssetManager: Unknown manager state.
- Could not load a native cube texture.
- No Physics Engine available.
- Plugin version is incorrect. Expected version 2.
- No Physics Plugin available.
AI-assisted analysis of BabylonJS/Babylon.js@0592b347b8 (2026-08-30).
Data as JSON: /api/errors/f19f1caba6def22c.
Report an issue: GitHub.