BabylonJS/Babylon.js · error
Restoring persistent anchors requires the anchor system to b
Error message
Restoring persistent anchors requires the anchor system to be attached
What it means
restorePersistentAnchorAsync resolves a persisted handle back into a tracked anchor, which requires an active, attached WebXR feature. If the anchor system is not currently attached to a session, the method cannot interact with the XRSession and throws this error before attempting the native restore. It is a state error, not a capability error.
Source
Thrown at packages/dev/core/src/XR/features/WebXRAnchorSystem.pure.ts:331
public async requestPersistentHandleAsync(anchor: IWebXRAnchor): Promise<string> {
const requestPersistentHandle = anchor.xrAnchor.requestPersistentHandle;
if (!requestPersistentHandle) {
throw new Error("Requesting persistent anchor handles is not supported in this environment/browser");
}
const handle = await requestPersistentHandle.call(anchor.xrAnchor);
this._setPersistentHandle(anchor, handle);
return handle;
}
/**
* Restore a persistent anchor into the Babylon anchor lifecycle
* @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;
View on GitHub (pinned to 0592b347b8)
Solutions
- Only call restore after the session is running and the anchor system is attached (e.g. after onXRSessionStarted)
- Check anchorSystem.attached before invoking
- Ensure the feature is enabled via the WebXR experience helper so attach happens automatically
- Wrap in try/catch and defer restoration until attach completes
Example fix
// before
await anchorSystem.restorePersistentAnchorAsync(handle);
// after
if (anchorSystem.attached) {
await anchorSystem.restorePersistentAnchorAsync(handle);
} else {
xrSessionManager.onXRSessionStarted.addOnce(() =>
anchorSystem.restorePersistentAnchorAsync(handle)
);
} Defensive patterns
Strategy: validation
Validate before calling
if (!anchorSystem.attached) {
throw new Error('attach the anchor system before restoring persistent anchors');
} Type guard
function isAttached(s: WebXRAnchorSystem): boolean {
return s.attached;
} Try / catch
try {
await anchorSystem.restorePersistentAnchorAsync(handle);
} catch (e) {
if (/attached/.test((e as Error).message)) {
xrSessionManager.onXRSessionStarted.addOnce(() => anchorSystem.restorePersistentAnchorAsync(handle));
}
} Prevention
- Restore anchors only after onXRSessionStarted fires
- Check .attached before any restore call
- Register the anchor feature with the experience helper so attach is automatic
- Cancel/defer restore flows during XR teardown
When it happens
Trigger: Calling restorePersistentAnchorAsync(handle) (directly or through restorePersistentAnchorsAsync) on a WebXRAnchorSystem instance that has not been attached — e.g. before the XR session starts or after the feature detached/session ended.
Common situations: Restoring anchors during app startup before entering XR, session ended asynchronously while restore logic was still running, forgetting to add the anchor system feature to the experience helpers.
Related errors
- Persistent anchor restoration was interrupted before trackin
- Anchors not enabled in this environment/browser
- String(error)
- Persistent anchor enumeration is not supported in this envir
- Requesting persistent anchor handles is not supported in thi
AI-assisted analysis of BabylonJS/Babylon.js@0592b347b8 (2026-08-30).
Data as JSON: /api/errors/95bcc92fc3f96778.
Report an issue: GitHub.