BabylonJS/Babylon.js · error · RangeError
The XR view index must be a non-negative integer.
Error message
The XR view index must be a non-negative integer.
What it means
The viewIndex argument passed to _getCurrentXRView (via view()) must be a whole number >= 0 because it indexes into pose.views, a JavaScript array of XRViews. Non-integer or negative values can never map to a view, so a RangeError is thrown up front before any WebXR API is touched.
Source
Thrown at packages/dev/core/src/XR/webXRSessionManager.ts:289
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
*/
public _getGraphicsBinding(): WebXRGraphicsBinding {
if (!this._engine) {
throw new Error("Cannot create the XR graphics binding: the engine has been disposed.");
View on GitHub (pinned to 0592b347b8)
Solutions
- Pass a non-negative integer index (0, 1, ...) matching the eye/view you want.
- Sanitize the value first: use Math.floor for derived floats and validate `Number.isInteger(i) && i >= 0` before the call.
- If you have an eye constant, map it to the correct integer index before calling view().
- Loop over views using pose.views.length bounds rather than a hard-coded upper limit.
Example fix
// before
const idx = eyes.length / 2; // 1.5 -> throws
const v = xr.view(idx);
// after
const idx = Math.floor(eyes.length / 2);
if (Number.isInteger(idx) && idx >= 0) {
const v = xr.view(idx);
} Defensive patterns
Strategy: validation
Validate before calling
const viewIndex: unknown = getUserIndex();
if (typeof viewIndex !== 'number' || !Number.isInteger(viewIndex) || viewIndex < 0) {
throw new RangeError('view index must be a non-negative integer');
}
const v = xr.view(viewIndex); Type guard
function isValidXRViewIndex(i: unknown): i is number {
return typeof i === 'number' && Number.isInteger(i) && i >= 0;
} Try / catch
try {
const v = xr.view(idx);
} catch (e) {
if (e instanceof RangeError && e.message.includes('non-negative integer')) {
console.error(`Bad view index: ${idx}`);
return;
}
throw e;
} Prevention
- Type view-index variables as number and validate at boundaries
- Map eye constants/enums to integer indices before calling view()
- Use Math.floor/|0 on computed indices
- Avoid NaN-producing expressions feeding the index (guard divisions/parses)
When it happens
Trigger: Calling view(-1), view(0.5), view(NaN) or view(undefined coerced) — typically from a loop with a wrong bound, from Math.random-derived values, or by passing an eye identifier string/enum instead of an integer index.
Common situations: Iterating views with a wrong increment; confusing eye enums (LEFT/RIGHT) with numeric indices; a variable that was expected to be an eye index but holds a float from a division or a NaN from a failed parse.
Related errors
- Sample2DRgbaToRef: widthPx and heightPx must be positive.
- Sample2DRgbaToRef: data length (${data.length}) is less than
- Invalid Space Warp framebuffer
- Multiview is not supported
- The provided canvas is null or undefined.
AI-assisted analysis of BabylonJS/Babylon.js@0592b347b8 (2026-08-30).
Data as JSON: /api/errors/28c9257622ac42e2.
Report an issue: GitHub.