{"record":{"id":"a7542773be34fdf7","repo":"BabylonJS/Babylon.js","slug":"dynamic-viewport-scaling-requires-an-initialized-x","errorCode":null,"errorMessage":"Dynamic viewport scaling requires an initialized XR reference space.","messagePattern":"Dynamic viewport scaling requires an initialized XR reference space\\.","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/dev/core/src/XR/webXRSessionManager.ts","lineNumber":286,"sourceCode":"     * @see https://playground.babylonjs.com/#BAGIIM#0\r\n     */\r\n    public requestViewportScale(viewIndex: number, scale: Nullable<number>): void {\r\n        const view = this._getCurrentXRView(viewIndex);\r\n        if (!(\"recommendedViewportScale\" in view) || typeof view.requestViewportScale !== \"function\") {\r\n            throw new Error(`Dynamic viewport scaling is not supported for XR view ${viewIndex}.`);\r\n        }\r\n        view.requestViewportScale(scale);\r\n    }\r\n\r\n    private _getCurrentXRView(viewIndex: number): XRView {\r\n        if (!this.inXRSession || !this.session) {\r\n            throw new Error(\"Dynamic viewport scaling requires an active XR session.\");\r\n        }\r\n        if (!this.inXRFrameLoop || !this.currentFrame) {\r\n            throw new Error(\"Dynamic viewport scaling must be used during an active XR frame.\");\r\n        }\r\n        if (!this._referenceSpaceInitialized) {\r\n            throw new Error(\"Dynamic viewport scaling requires an initialized XR reference space.\");\r\n        }\r\n        if (!Number.isInteger(viewIndex) || viewIndex < 0) {\r\n            throw new RangeError(\"The XR view index must be a non-negative integer.\");\r\n        }\r\n\r\n        const pose = this.currentFrame.getViewerPose(this.referenceSpace);\r\n        if (!pose || viewIndex >= pose.views.length) {\r\n            throw new RangeError(`XR view ${viewIndex} is not available in the current viewer pose.`);\r\n        }\r\n        return pose.views[viewIndex];\r\n    }\r\n\r\n    /**\r\n     * Obtains the XR graphics binding for the current session, creating it lazily.\r\n     * This is the API-agnostic seam used by WebGL and WebGPU XR features to share a binding.\r\n     * @returns the XR graphics binding for the current session\r\n     * @internal\r\n     */\r","sourceCodeStart":268,"sourceCodeEnd":304,"githubUrl":"https://github.com/BabylonJS/Babylon.js/blob/0592b347b8a4ee0236089ea86a749cacfdb266d8/packages/dev/core/src/XR/webXRSessionManager.ts#L268-L304","documentation":"_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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["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().","Defer viewport access until after the first successful frame; guard with `if (sessionManager.referenceSpace)`.","Listen for the session initialized event/observable and only enable XR-dependent code afterwards.","Request the desired reference space type explicitly during initialization instead of relying on default 'local-floor' resolution."],"exampleFix":"// before\nawait xr.setSessionAsync(session);\nconst v = xr.view(0); // may throw: reference space not yet initialized\n// after\nawait xr.setSessionAsync(session);\nawait xr.setReferenceSpaceTypeAsync('local-floor'); // resolves reference space first\nconst v = xr.view(0);","handlingStrategy":"validation","validationCode":"if (!xr.referenceSpace) {\n  await xr.setReferenceSpaceTypeAsync('local-floor'); // ensure reference space resolved\n}\nconst v = xr.view(0);","typeGuard":"function referenceSpaceReady(xr: WebXRSessionManager): boolean {\n  return xr.referenceSpace != null;\n}","tryCatchPattern":"try {\n  const v = xr.view(0);\n} catch (e) {\n  if (e instanceof Error && e.message.includes('reference space')) {\n    await xr.setReferenceSpaceTypeAsync('local-floor');\n    const v = xr.view(0); // retry once initialized\n  } else {\n    throw e;\n  }\n}","preventionTips":["Use Helper.createDefaultSessionAsync / setReferenceSpaceTypeAsync before rendering","Skip XR-dependent logic until the session is fully initialized","Do not query views on the very first frame after sessionstart without checking referenceSpace","Explicitly request the reference space type you need instead of relying on defaults"],"tags":["webxr","reference-space","initialization-order"],"backgroundTag":"xr-reference-space-not-initialized","analyzedSha":"0592b347b8a4ee0236089ea86a749cacfdb266d8","analyzedAt":"2026-08-30T15:11:20.442Z","schemaVersion":2},"datasetVersion":"2026-08-30T18:17:15.746Z"}