BabylonJS/Babylon.js · error

Unsafe FBX object ID ${value.toString()}: object IDs must be

Error message

Unsafe FBX object ID ${value.toString()}: object IDs must be safe integers.

What it means

FBX object IDs are int64 values, but this library represents them as JS numbers and only accepts values within the IEEE-754 safe-integer range (2^53-1). getSafeFBXObjectId throws when a numeric ID exceeds Number.MAX_SAFE_INTEGER (or is non-integral), because downstream comparisons and maps would silently lose precision. Non-number inputs return undefined instead of throwing.

Source

Thrown at packages/dev/loaders/src/FBX/types/fbxTypes.ts:85

/** Extract a property value by index, with type narrowing */
export function getPropertyValue<T extends FBXPropertyValue>(node: FBXNode, index: number): T | undefined {
    if (index < node.properties.length) {
        return node.properties[index].value as T;
    }
    return undefined;
}

/**
 * Converts an FBX object ID value to a safe JavaScript number.
 * @param value - Parsed FBX object ID value
 * @returns The object ID, or undefined when the value is not numeric
 */
export function getSafeFBXObjectId(value: unknown): number | undefined {
    if (typeof value !== "number") {
        return undefined;
    }
    if (!Number.isSafeInteger(value)) {
        throw new Error(`Unsafe FBX object ID ${value.toString()}: object IDs must be safe integers.`);
    }
    return value;
}

/** Get the numeric ID from a node (first property is typically the int64 UID) */
export function getNodeId(node: FBXNode): number | undefined {
    const prop = node.properties[0];
    if (prop && (prop.type === "int64" || prop.type === "int32")) {
        return getSafeFBXObjectId(prop.value);
    }
    return undefined;
}

/**
 * Clean FBX object names.
 * FBX names may contain:
 *   - A "Class::" prefix (e.g. "Model::valkyrie_mesh") — strip it
 *   - A binary null/control-character class suffix — strip it

View on GitHub (pinned to 0592b347b8)

Solutions

  1. Validate/sanitize the source data: check IDs against Number.isSafeInteger before use.
  2. If you control export, configure the exporter to emit smaller/sequential IDs.
  3. If you must handle big IDs, adapt the code path to parse IDs with BigInt instead of number.
  4. Return undefined instead of calling getSafeFBXObjectId when the value may be unsafe, and skip/repair that node.

Example fix

// before
const id = getNodeId(node); // throws for huge int64 UIDs
// after
const raw = Number(node.properties[0]);
const id = Number.isSafeInteger(raw) ? raw : undefined;
if (id === undefined) console.warn("Skipping node with unsafe FBX ID", raw);
Defensive patterns

Strategy: validation

Validate before calling

const raw = node.properties?.[0];
if (typeof raw !== "number" || !Number.isSafeInteger(raw)) {
  throw new Error(`FBX node ID ${raw} is not a safe integer`);
}

Type guard

function isSafeFBXId(value: unknown): value is number {
  return typeof value === "number" && Number.isSafeInteger(value);
}

Try / catch

let id: number | undefined;
try {
  id = getNodeId(node);
} catch (e) {
  if (String(e.message).startsWith("Unsafe FBX object ID")) {
    console.warn("Skipping node with unsafe int64 ID");
    id = undefined;
  } else throw e;
}

Prevention

When it happens

Trigger: Calling getSafeFBXObjectId (directly or via toObjectNumber/getNodeId) with a number parsed from an FBX node whose int64 UID is larger than 9007199254740991.

Common situations: FBX files authored in tools that generate large 64-bit UIDs (common in modern exporters); hand-rolling parsers that convert node ID strings with Number() instead of BigInt.

Related errors


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