BabylonJS/Babylon.js · error

Cannot create the XR graphics binding before the XR session

Error message

Cannot create the XR graphics binding before the XR session is initialized.

What it means

The XR graphics binding must be created with a live XRSession (WebGL/WebGPU binding constructors take the session). _getGraphicsBinding throws if this.session is null, i.e. the manager has no initialized session yet — the binding cannot exist before a session does.

Source

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

        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
     */
    public _getGraphicsBinding(): WebXRGraphicsBinding {
        if (!this._engine) {
            throw new Error("Cannot create the XR graphics binding: the engine has been disposed.");
        }
        if (!this.session) {
            throw new Error("Cannot create the XR graphics binding before the XR session is initialized.");
        }
        if (!this._graphicsBinding) {
            this._graphicsBinding = this._engine.isWebGPU
                ? WebXRWebGPUGraphicsBinding.CreateFromEngine(this.session, this._engine)
                : WebXRWebGLGraphicsBinding.CreateFromEngine(this.session, this._engine);
        }
        return this._graphicsBinding;
    }

    /**
     * Creates a WebXRRenderTarget object for the XR session
     * @param options optional options to provide when creating a new render target
     * @returns a WebXR render target to which the session can render
     */
    public getWebXRRenderTarget(options?: WebXRManagedOutputCanvasOptions): WebXRRenderTarget {
        const engine = this.scene.getEngine();
        if (this._xrNavigator.xr.native) {
            return new NativeXRRenderTarget(this);

View on GitHub (pinned to 0592b347b8)

Solutions

  1. Start the session first (await xr.initializeAsync(); await xr.setSessionAsync(...) or Helper.createDefaultSessionAsync) before any code that touches graphics bindings.
  2. Check `xr.sessionManager.session != null` before creating layers/features that need the binding.
  3. Initialize features after the session is ready — use onXRSessionInit / session observables rather than constructor-time setup.
  4. Create a fresh session manager per session instead of reusing one whose session ended.

Example fix

// before
const xr = new WebXRSessionManager(scene);
const provider = new WebXRWebGLRenderTargetTextureProvider(engine, xr.sessionManager); // no session yet
// after
const xr = new WebXRSessionManager(scene);
await xr.setSessionAsync(await navigator.xr.requestSession('immersive-vr'));
const provider = new WebXRWebGLRenderTargetTextureProvider(engine, xr.sessionManager);
Defensive patterns

Strategy: validation

Validate before calling

if (!xr.session) {
  throw new Error('XR session must be started before creating graphics bindings');
}
const binding = xr._getGraphicsBinding();

Type guard

function sessionActive(xr: WebXRSessionManager): xr is WebXRSessionManager & { session: XRSession } {
  return xr.session != null;
}

Try / catch

try {
  const binding = xr._getGraphicsBinding();
} catch (e) {
  if (e instanceof Error && e.message.includes('before the XR session')) {
    console.warn('Graphics binding requested before session start — deferring');
    return null;
  }
  throw e;
}

Prevention

When it happens

Trigger: Calling _getGraphicsBinding() (or a layer/feature that requests it) after creating the WebXRSessionManager but before initializeAsync/setSession established a session; using a manager whose session ended and was cleared; attempting to register a WebXR layer manually without starting a session first.

Common situations: Instantiating WebXRLayerRenderTargetTextureProvider or custom composition layers at setup time instead of after session start; a feature's attach() running before the session promise resolved; reusing a session manager object after session end for a new attempt.

Related errors


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