BabylonJS/Babylon.js · error
${method}: local range [${offset}, ${offset + count}) is out
Error message
${method}: local range [${offset}, ${offset + count}) is outside the reserved region [0, ${state.capacity}) What it means
Streaming part writes are expressed in local coordinates [0, capacity) of the reserved region; the handle adds the region base internally. assertLocalRange throws when offset/count are non-integers, negative, or offset+count exceeds the part's reserved capacity, preventing a handle from addressing a neighboring part's texels.
Source
Thrown at packages/dev/core/src/Meshes/GaussianSplatting/gaussianSplattingMesh.pure.ts:2194
const compound = this;
const applyBounds = () => {
if (boundsMin.x <= boundsMax.x) {
proxy.setBoundingInfo(new BoundingInfo(boundsMin.clone(), boundsMax.clone()));
compound._updateBoundingInfoFromProxies();
}
};
// Rejects any mutating call after the part was removed, so a retained stale handle can't touch a surviving
// part that inherited this region's (now-reused) part index/base.
const assertLive = (method: string) => {
if (state.removed) {
throw new Error(`${method}: this streaming part has been removed`);
}
};
// Enforces the documented local part boundary [0, capacity) so a handle call can never address another
// part's atlas region (the region base is added to these local coordinates before use).
const assertLocalRange = (method: string, offset: number, count: number) => {
if (!Number.isInteger(offset) || !Number.isInteger(count) || offset < 0 || count < 0 || offset + count > state.capacity) {
throw new Error(`${method}: local range [${offset}, ${offset + count}) is outside the reserved region [0, ${state.capacity})`);
}
};
const handle: IGaussianSplattingStreamingPart = {
proxy,
capacity,
get partIndex() {
return state.partIndex;
},
get base() {
return state.base;
},
get centersTexture() {
return compound.centersTexture;
},
get covariancesATexture() {
return compound.covariancesATexture;
},
View on GitHub (pinned to 0592b347b8)
Solutions
- Use offset/count values within the capacity returned by reserveStreamingPart and clamp offset + count to capacity
- Validate Number.isInteger(offset) && Number.isInteger(count) && offset >= 0 && count >= 0 before calling
- Split large writes into chunks that fit the reserved region
Example fix
// before
part.writeSplats(globalOffset, data); // atlas-level offset
// after
const local = globalOffset - partBase;
if (local >= 0 && local + data.length / 32 <= part.capacity) {
part.writeSplats(local, data);
} Defensive patterns
Strategy: validation
Validate before calling
const ok = Number.isInteger(offset) && Number.isInteger(count) && offset >= 0 && count >= 0 && offset + count <= part.capacity;
if (!ok) throw new RangeError(`[${offset}, ${offset + count}) outside [0, ${part.capacity})`); Type guard
const inRange = (o: number, c: number, cap: number) => Number.isInteger(o) && Number.isInteger(c) && o >= 0 && c >= 0 && o + c <= cap;
Try / catch
try {
handle.writeSplats(offset, data);
} catch (e) {
if (String(e).includes('outside the reserved region')) {
const n = Math.floor((handle.capacity - offset));
if (n > 0) handle.writeSplats(offset, data.subarray(0, n * 32));
} else throw e;
} Prevention
- Always express writes in local part coordinates, never atlas-global ones
- Clamp count to capacity - offset before writing
- Keep the part's returned capacity alongside the handle
When it happens
Trigger: Calling a part's write method with offset or count beyond the capacity returned when the part was reserved, with fractional values, or with negative values.
Common situations: Assuming capacity equals the full atlas size; off-by-one errors (offset + count == capacity is valid, > capacity is not); reserving a smaller part than the producer emits.
Related errors
- GaussianSplattingDebugger.addMesh: mesh must have a Gaussian
- To call addPart()/addParts(), each source mesh must not be a
- reserveStreamingPart: shTextureCount ${shTextureCount} does
- Gaussian splat data byte length (${bytes.byteLength}) is not
- _writeStreamingSplats: range [${globalOffset}, ${globalOffse
AI-assisted analysis of BabylonJS/Babylon.js@0592b347b8 (2026-08-30).
Data as JSON: /api/errors/30cfacab12240588.
Report an issue: GitHub.