BabylonJS/Babylon.js · error

Dynamic viewport scaling requires an initialized XR referenc

Error message

Dynamic viewport scaling requires an initialized XR reference space.

What it means

_getCurrentXRView needs a resolved XRReferenceSpace to call frame.getViewerPose(). The manager initializes the reference space asynchronously after the session starts (_referenceSpaceInitialized). If view() is called while the frame loop is running but the reference space has not yet been resolved, there is no coordinate system to obtain the viewer pose in, so this error is thrown.

Source

Thrown at packages/dev/core/src/XR/webXRSessionManager.ts:286

     * @see https://playground.babylonjs.com/#BAGIIM#0
     */
    public requestViewportScale(viewIndex: number, scale: Nullable<number>): void {
        const view = this._getCurrentXRView(viewIndex);
        if (!("recommendedViewportScale" in view) || typeof view.requestViewportScale !== "function") {
            throw new Error(`Dynamic viewport scaling is not supported for XR view ${viewIndex}.`);
        }
        view.requestViewportScale(scale);
    }

    private _getCurrentXRView(viewIndex: number): XRView {
        if (!this.inXRSession || !this.session) {
            throw new Error("Dynamic viewport scaling requires an active XR session.");
        }
        if (!this.inXRFrameLoop || !this.currentFrame) {
            throw new Error("Dynamic viewport scaling must be used during an active XR frame.");
        }
        if (!this._referenceSpaceInitialized) {
            throw new Error("Dynamic viewport scaling requires an initialized XR reference space.");
        }
        if (!Number.isInteger(viewIndex) || viewIndex < 0) {
            throw new RangeError("The XR view index must be a non-negative integer.");
        }

        const pose = this.currentFrame.getViewerPose(this.referenceSpace);
        if (!pose || viewIndex >= pose.views.length) {
            throw new RangeError(`XR view ${viewIndex} is not available in the current viewer pose.`);
        }
        return pose.views[viewIndex];
    }

    /**
     * Obtains the XR graphics binding for the current session, creating it lazily.
     * This is the API-agnostic seam used by WebGL and WebGPU XR features to share a binding.
     * @returns the XR graphics binding for the current session
     * @internal
     */

View on GitHub (pinned to 0592b347b8)

Solutions

  1. Wait for the manager's reference-space initialization before rendering/querying views — e.g. await the session start helper (Helper.createDefaultSessionAsync) or check sessionManager._referenceSpaceInitialized / referenceSpace before calling view().
  2. Defer viewport access until after the first successful frame; guard with `if (sessionManager.referenceSpace)`.
  3. Listen for the session initialized event/observable and only enable XR-dependent code afterwards.
  4. Request the desired reference space type explicitly during initialization instead of relying on default 'local-floor' resolution.

Example fix

// before
await xr.setSessionAsync(session);
const v = xr.view(0); // may throw: reference space not yet initialized
// after
await xr.setSessionAsync(session);
await xr.setReferenceSpaceTypeAsync('local-floor'); // resolves reference space first
const v = xr.view(0);
Defensive patterns

Strategy: validation

Validate before calling

if (!xr.referenceSpace) {
  await xr.setReferenceSpaceTypeAsync('local-floor'); // ensure reference space resolved
}
const v = xr.view(0);

Type guard

function referenceSpaceReady(xr: WebXRSessionManager): boolean {
  return xr.referenceSpace != null;
}

Try / catch

try {
  const v = xr.view(0);
} catch (e) {
  if (e instanceof Error && e.message.includes('reference space')) {
    await xr.setReferenceSpaceTypeAsync('local-floor');
    const v = xr.view(0); // retry once initialized
  } else {
    throw e;
  }
}

Prevention

When it happens

Trigger: Calling view(index) during the first XR frame(s) after session start, before the promise from sessionManager.initializeReferenceSpaceAsync / the internal reference-space setup resolves; running code on sessionstart event that immediately queries views.

Common situations: Subscribing to onXRFrameObservable or the scene's render loop on the very first frame after entering XR and assuming reference space is ready; race conditions where sessionManager.referenceSpace is still null.

Related errors


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