dotnet/runtime · error · Error
index out of range
Error message
index out of range
What it means
Thrown by WasmRootBufferImpl._throw_index_out_of_range (via _check_in_range) when a get/set/get_address/copy operation is given an index that is < 0 or >= the buffer's capacity. It is the standard bounds-check for the root-buffer array accessors.
Source
Thrown at src/mono/browser/runtime/roots.ts:184
private __offset: VoidPtr;
private __offset32: number;
private __handle: number;
private __ownsAllocation: boolean;
constructor (offset: VoidPtr, capacity: number, ownsAllocation: boolean, name?: string) {
const capacityBytes = capacity * 4;
this.__offset = offset as any >>> 0 as any;
this.__offset32 = <number><any>offset >>> 2;
this.__count = capacity;
this.length = capacity;
mono_assert(!WasmEnableThreads || !gc_locked, "GC must not be locked when creating a GC root");
this.__handle = cwraps.SystemInteropJS_RegisterGCRoot(offset, capacityBytes, name || "noname");
this.__ownsAllocation = ownsAllocation;
}
_throw_index_out_of_range (): void {
throw new Error("index out of range");
}
_check_in_range (index: number): void {
if ((index >= this.__count) || (index < 0))
this._throw_index_out_of_range();
}
get_address (index: number): MonoObjectRef {
this._check_in_range(index);
return <any>this.__offset + (index * 4);
}
get_address_32 (index: number): number {
this._check_in_range(index);
return this.__offset32 + index;
}
// NOTE: These functions do not use the helpers from memory.ts because WasmRoot.get and WasmRoot.setView on GitHub (pinned to 60108ba66e)
Solutions
- Check 0 <= index < buffer.length (or __count) before accessing.
- Use exclusive upper bounds in loops: for (let i = 0; i < buf.length; i++).
- Ensure the buffer has not been released before indexing into it.
Example fix
// before for (let i = 0; i <= buf.length; i++) buf.get(i); // off-by-one // after for (let i = 0; i < buf.length; i++) buf.get(i);
Defensive patterns
Strategy: validation
Validate before calling
function safeGet(buf: WasmRootBuffer, index: number) {
if (index < 0 || index >= buf.length) throw new RangeError(`index ${index} out of [0,${buf.length})`);
return buf.get(index);
} Type guard
function inRange(buf: { length: number }, i: unknown): i is number {
return typeof i === 'number' && Number.isInteger(i) && i >= 0 && i < buf.length;
} Prevention
- Use exclusive upper bounds: i < buf.length.
- Re-check length right before indexing if the buffer may have been released.
- Do not mix raw pointer offsets with root-buffer indices.
When it happens
Trigger: Calling buf.get(i), buf.set(i, v), buf.get_address(i), buf.copy_value_from_address(i, ...) with i outside [0, capacity). Common with an off-by-one loop bound or a stale capacity after release().
Common situations: Looping with <= instead of <; using an index computed from a different-sized structure; reading length after the buffer was released (capacity collapses to 0); passing a raw pointer offset where an index was expected.
Related errors
- capacity >= 1
- address must be a location in the native heap
- value must be an address in the managed heap
- count_or_values must be either an array or a number greater
- Expected runtimeOptions to be an array of strings
AI-assisted analysis of dotnet/runtime@60108ba66e (2026-08-10).
Data as JSON: /api/errors/a6ce9ba6fade980f.
Report an issue: GitHub.