BabylonJS/Babylon.js · error

Persistent anchor restoration was interrupted before trackin

Error message

Persistent anchor restoration was interrupted before tracking began

What it means

During restorePersistentAnchorAsync, after awaiting the native restorePersistentAnchor call, the code re-checks that the feature is still attached and that the session has not changed (e.g. session ended and a new one started). If that invariant broke while awaiting, the freshly restored native anchor is deleted and this error is thrown — the restore was valid on the native side but can no longer be surfaced to the caller.

Source

Thrown at packages/dev/core/src/XR/features/WebXRAnchorSystem.pure.ts:343

     * @param handle The persistent anchor handle to restore
     * @returns A promise that resolves after the restored anchor is tracked by an XR frame
     * @throws If restoring persistent anchors is not supported by the current session
     */
    public async restorePersistentAnchorAsync(handle: string): Promise<IWebXRAnchor> {
        if (!this.attached) {
            throw new Error("Restoring persistent anchors requires the anchor system to be attached");
        }

        const session = this._xrSessionManager.session;
        const restorePersistentAnchor = session?.restorePersistentAnchor;
        if (!restorePersistentAnchor) {
            throw new Error("Restoring persistent anchors is not supported in this environment/browser");
        }

        const nativeAnchor = await restorePersistentAnchor.call(session, handle);
        if (!this.attached || this._xrSessionManager.session !== session) {
            nativeAnchor.delete();
            throw new Error("Persistent anchor restoration was interrupted before tracking began");
        }
        const existingAnchorIndex = this._findIndexInAnchorArray(nativeAnchor);
        if (existingAnchorIndex !== -1) {
            const existingAnchor = this._trackedAnchors[existingAnchorIndex];
            existingAnchor.persistentHandle = handle;
            return existingAnchor;
        }

        return await new Promise<IWebXRAnchor>((resolve, reject) => {
            this._futureAnchors.push({
                nativeAnchor,
                resolved: false,
                submitted: true,
                persistentHandle: handle,
                resolve,
                reject,
            });
        });

View on GitHub (pinned to 0592b347b8)

Solutions

  1. Catch this error and treat the handle as un-restored; optionally retry after the next session starts
  2. Stop XR teardown until pending anchor restorations settle (await Promise.all before dispose)
  3. Listen to session end events and cancel/ignore in-flight restoration bookkeeping
  4. Re-run restorePersistentAnchorsAsync on the new session once attached

Example fix

// before
await anchorSystem.restorePersistentAnchorsAsync();
disposeXr();
// after
await anchorSystem.restorePersistentAnchorsAsync();
// then, guarded by no pending work:
await Promise.allSettled(pendingRestores);
disposeXr();
Defensive patterns

Strategy: try-catch

Validate before calling

// wait for all in-flight restores before ending the session or disposing XR
await Promise.allSettled(pendingRestorePromises);
if (anchorSystem.attached && xrSessionManager.session) {
  // safe to proceed
}

Type guard

function restoreStillValid(anchorSystem: WebXRAnchorSystem, session: XRSession): boolean {
  return anchorSystem.attached && anchorSystem['_xrSessionManager'].session === session;
}

Try / catch

try {
  const anchor = await anchorSystem.restorePersistentAnchorAsync(handle);
} catch (e) {
  if (/interrupted/.test((e as Error).message)) {
    console.warn('session changed during restore; retry on next session');
  }
}

Prevention

When it happens

Trigger: The XR session ends or the anchor system detaches/reattaches (or _xrSessionManager.session is swapped) between the restorePersistentAnchor call and its completion — typically user exits VR mid-restore or app tears down XR during startup restoration.

Common situations: Race conditions when restoring many persistent anchors at app entry while the user exits the headset, timeout/disconnect of the session, calling restorePersistentAnchorsAsync while simultaneously disposing the scene/XR helpers.

Related errors


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