BabylonJS/Babylon.js · error

SmartAssetSerializer: Invalid asset map — 'assets' must be a

Error message

SmartAssetSerializer: Invalid asset map — 'assets' must be an object.

What it means

DeserializeSmartAssetMap validates the shape of a serialized smart-asset map document. After checking the version equals 1, it requires doc.assets to be a plain object (record of key -> entry). This error is thrown when 'assets' is missing, null, not an object, or is an Array, because the deserializer cannot iterate asset entries otherwise.

Source

Thrown at packages/dev/core/src/SmartAssets/smartAssetSerializer.ts:53

/**
 * Validates and parses a serialized smart asset map document.
 * @param data - The raw data to validate (typically parsed JSON).
 * @returns The validated document.
 * @throws If the data does not conform to the expected schema.
 */
export function DeserializeSmartAssetMap(data: unknown): ISerializedSmartAssetMap {
    if (!data || typeof data !== "object") {
        throw new Error("SmartAssetSerializer: Invalid asset map — expected an object.");
    }

    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.

View on GitHub (pinned to 0592b347b8)

Solutions

  1. Inspect the JSON document and ensure it has a top-level 'assets' key holding a plain object of key -> {url,...} entries.
  2. If your data is an array of entries, convert it to a keyed object map before deserializing (e.g. Object.fromEntries(entries.map(e => [e.name, e]))).
  3. Verify you are passing the correct document (the asset map doc with version:1 and assets), not a parent project object or a sub-field.
  4. Re-export the asset map from the tool that produced it to regenerate a valid version-1 document.

Example fix

// before
const doc = JSON.parse(raw);
await DeserializeSmartAssetMap(doc); // doc.assets missing / is an array

// after
const parsed = JSON.parse(raw);
const doc = {
  version: 1,
  assets: Array.isArray(parsed.assets)
    ? Object.fromEntries(parsed.assets.map(a => [a.name, a]))
    : (parsed.assets ?? {})
};
await DeserializeSmartAssetMap(doc);
Defensive patterns

Strategy: validation

Validate before calling

function isValidAssetMapDoc(doc) {
  return !!doc && typeof doc === "object" &&
    doc.version === 1 &&
    typeof doc.assets === "object" &&
    doc.assets !== null &&
    !Array.isArray(doc.assets);
}
if (!isValidAssetMapDoc(parsed)) throw new Error("Not a valid v1 smart-asset map document");

Type guard

function isAssetMapDoc(doc): doc is { version: 1; assets: Record<string, unknown> } {
  return typeof doc === "object" && doc !== null &&
    (doc as any).version === 1 &&
    typeof (doc as any).assets === "object" &&
    (doc as any).assets !== null &&
    !Array.isArray((doc as any).assets);
}

Try / catch

try {
  const map = DeserializeSmartAssetMap(doc);
} catch (e) {
  if (e.message.includes("'assets' must be an object")) {
    console.error("Asset map document malformed: missing or non-object 'assets'", doc);
  } else throw e;
}

Prevention

When it happens

Trigger: Calling DeserializeSmartAssetMap with a parsed JSON doc where: doc.assets is undefined/omitted; doc.assets is null; doc.assets is an array (e.g. [{...},{...}] instead of {"a": {...}}); or doc.assets is a primitive like a string or number.

Common situations: Hand-edited or truncated asset-map JSON files exported from another tool; a producer exporting assets as a JSON array instead of a keyed map; an older/newer export format where the assets were stored under a different key (e.g. 'assetMap' or nested), leaving doc.assets undefined; template literal string interpolation passing the wrong object level (passing the whole project instead of doc.assets).

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/4a5d83daf1608ee6. Report an issue: GitHub.