BabylonJS/Babylon.js · error

OverrideManager: Unknown manager state.

Error message

OverrideManager: Unknown manager state.

What it means

GetOverrideInternals looks up per-manager hidden state in a WeakMap (OverrideManagerInternals); if the manager instance has no entry, the manager was never initialized (or was constructed outside the library's init path). Since WeakMap entries vanish when the manager is garbage-collected, a stale reference can also trigger this.

Source

Thrown at packages/dev/sharedUiComponents/src/projects/overrideManager.ts:452

        internal.sceneDisposeObserver = null;
    }

    internal.overrides.length = 0;
    internal.originalValues.clear();

    manager.onChangedObservable.clear();

    if (manager.scene.metadata) {
        delete manager.scene.metadata[OverrideManagerKey];
    }
}

// ── Private ──

function GetOverrideInternals(manager: OverrideManager): OverrideManagerInternals {
    const internal = OverrideManagerInternals.get(manager);
    if (!internal) {
        throw new Error("OverrideManager: Unknown manager state.");
    }
    return internal;
}

/**
 * Applies a single override entry to its target, capturing the original value
 * on the first application so {@link RemoveOverride} can restore it later.
 * @param manager - The override manager owning the entry.
 * @param internal - The manager's internal state.
 * @param entry - The override to apply.
 */
function ApplyOverrideEntry(manager: OverrideManager, internal: OverrideManagerInternals, entry: IOverrideEntry): void {
    const target = ResolveTarget(manager.scene, entry.targetType, entry.targetName, entry.targetIndex);
    if (!target) {
        Logger.Warn(`OverrideManager: target not found for type="${entry.targetType}" name="${entry.targetName}" index=${entry.targetIndex} prop="${entry.propertyPath}"`);
        return; // Target not loaded yet — override will be applied on next ApplyAllOverrides
    }

View on GitHub (pinned to 0592b347b8)

Solutions

  1. Create the manager through the library's constructor so internals are registered.
  2. Hold the live manager instance; discard stale references after reload/reinit.
  3. Ensure initialization finished before calling GetOverrides or other public methods.
  4. Don't clone/deserialize manager objects; re-create them in the target context.

Example fix

// before
const mgr = Object.create(OverrideManager.prototype); // no internals
GetOverrides(mgr); // throws: Unknown manager state
// after
const mgr = new OverrideManager(scene); // registers internals
GetOverrides(mgr);
Defensive patterns

Strategy: try-catch

Validate before calling

// Only call public APIs on instances obtained from the library constructor
// const mgr = new OverrideManager(scene);
// if (!(mgr instanceof OverrideManager)) throw new Error("stale manager reference");

Type guard

function isLiveManager(m: unknown): m is OverrideManager {
  return m instanceof OverrideManager;
}

Try / catch

// try {
//   return GetOverrides(manager);
// } catch (e) {
//   if (String(e.message).includes("Unknown manager state")) {
//     manager = new OverrideManager(scene); // re-init stale/recreated manager
//     return GetOverrides(manager);
//   }
//   throw e;
// }

Prevention

When it happens

Trigger: Calling GetOverrides or other public OverrideManager APIs on an instance not created via the library's constructor/init; passing a different object than the real manager; using a manager after its internals were cleared; calling GetOverrideInternals before initialization completed.

Common situations: Constructing OverrideManager via Object.create or a framework deserializer bypassing the real constructor; manager recreated by a framework (e.g. hot reload) while callers keep the old reference; initialization step forgotten in a custom setup.

Related errors


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