BabylonJS/Babylon.js · error
SmartAssetSerializer: Invalid entry for key "${key}" — 'url'
Error message
SmartAssetSerializer: Invalid entry for key "${key}" — 'url' must be a non-empty string. What it means
Within DeserializeSmartAssetMap, after confirming an asset entry is an object, the deserializer requires entry.url to be a non-empty string. This error is thrown when the url property is missing, not a string (e.g. a number or object), or is an empty string, since the library cannot resolve the asset location without it.
Source
Thrown at packages/dev/core/src/SmartAssets/smartAssetSerializer.ts:63
const doc = data as Record<string, unknown>;
if (doc.version !== 1) {
throw new Error(`SmartAssetSerializer: Unsupported asset map version "${doc.version}". Expected version 1.`);
}
if (!doc.assets || typeof doc.assets !== "object" || Array.isArray(doc.assets)) {
throw new Error("SmartAssetSerializer: Invalid asset map — 'assets' must be an object.");
}
const assets = doc.assets as Record<string, unknown>;
for (const [key, entry] of Object.entries(assets)) {
if (!entry || typeof entry !== "object") {
throw new Error(`SmartAssetSerializer: Invalid entry for key "${key}" — expected an object.`);
}
const entryObj = entry as Record<string, unknown>;
if (typeof entryObj.url !== "string" || entryObj.url.length === 0) {
throw new Error(`SmartAssetSerializer: Invalid entry for key "${key}" — 'url' must be a non-empty string.`);
}
}
return data as ISerializedSmartAssetMap;
}
/**
* Returns true for `data:`, `blob:`, or any URL with an absolute protocol.
* @param url - The URL to inspect.
* @returns Whether the URL is absolute or a data/blob URI.
*/
export function IsAbsoluteOrSpecialUrl(url: string): boolean {
return url.startsWith("data:") || url.startsWith("blob:") || Tools.IsAbsoluteUrl(url);
}
/**
* Resolves an asset URL relative to a base URL.
* Absolute URLs (http://, https://) and data URIs are returned as-is.View on GitHub (pinned to 0592b347b8)
Solutions
- Add or correct the url field on the flagged entry (the key name is in the error message) so it is a non-empty string.
- Check for property-name mismatches (uri/src/path/href) and rename to 'url', or map the field before deserializing.
- Verify whatever builds the URL (env vars, base-CDN config) is not producing an empty string at export time.
- Pre-validate the map yourself and fail early with your own message listing all invalid keys, rather than one at a time.
Example fix
// before
const doc = { version: 1, assets: { logo: { uri: "https://cdn/logo.png" }, icon: { url: "" } } };
DeserializeSmartAssetMap(doc);
// after
const doc = {
version: 1,
assets: {
logo: { url: "https://cdn/logo.png" },
icon: { url: "https://cdn/icon.png" }
}
};
DeserializeSmartAssetMap(doc); Defensive patterns
Strategy: validation
Validate before calling
const badUrls = Object.entries(doc.assets ?? {})
.filter(([k, v]) => !v || typeof v !== "object" || typeof v.url !== "string" || v.url.length === 0)
.map(([k]) => k);
if (badUrls.length) throw new Error(`Entries with missing/empty url: ${badUrls.join(", ")}`); Type guard
function hasUrl(v: unknown): v is { url: string } {
return typeof v === "object" && v !== null &&
typeof (v as { url?: unknown }).url === "string" &&
(v as { url: string }).url.length > 0;
} Try / catch
try {
const map = DeserializeSmartAssetMap(doc);
} catch (e) {
const m = e.message.match(/key "([^"]+)" — 'url' must be a non-empty string/);
if (m) {
console.error(`Asset "${m[1]}" has no valid url; check exporter output / URL builder.`);
} else throw e;
} Prevention
- Use a single URL-builder helper so empty-string URLs (unset env/base URL) are caught early.
- Standardize on the 'url' property name; reject uri/src/path aliases at export time.
- Add a lint/schema check requiring a non-empty url string on every asset entry.
- Validate the exported asset map in CI before publishing.
When it happens
Trigger: An entry in doc.assets such as {"logo": {}} (url omitted), {"logo": {"url": ""}}, or {"logo": {"url": 123}} / {"url": {...}} — checked via typeof entryObj.url !== "string" || entryObj.url.length === 0 for each key during Object.entries iteration.
Common situations: Export tools writing placeholder entries with empty url for assets that failed to upload; hand-written maps where the property was misnamed (uri, src, path) leaving url undefined; URL builders returning an empty string when an env var like CDN_BASE was unset; numeric IDs pasted into the url field.
Understand the failure class
Background: Schema validation failed / invalid input schema: payload rejected because its shape doesn't match the expected schema — this error's family across 28 libraries.
Related errors
- SmartAssetSerializer: Invalid asset map — 'assets' must be a
- SmartAssetSerializer: Invalid entry for key "${key}" — expec
- ProjectFile: Invalid project file — 'overrides' must be an a
- ProjectFile: Invalid project file — 'companionBindings' must
- SmartAssetSerializer: Invalid asset map — expected an object
AI-assisted analysis of BabylonJS/Babylon.js@0592b347b8 (2026-08-30).
Data as JSON: /api/errors/3eb809658ede3339.
Report an issue: GitHub.