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

  1. 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.
  2. Check for property-name mismatches (uri/src/path/href) and rename to 'url', or map the field before deserializing.
  3. Verify whatever builds the URL (env vars, base-CDN config) is not producing an empty string at export time.
  4. 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

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


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