dotnet/runtime · error · Error
value was not an integer
Error message
value was not an integer
What it means
autoThrowI52 throws 'value was not an integer' when the native mono_wasm_f64_to_i52/u52 routine returns I52_ERROR_NON_INTEGRAL, meaning floor(value) != value. It is reached via setI52/setU52 (writing) and getI52/getU52 indirectly. These i52/u52 helpers store/load 52-bit integers in the wasm heap.
Source
Thrown at src/mono/browser/runtime/memory.ts:152
export function setI32_unchecked (offset: MemOffset, value: number): void {
receiveWorkerHeapViews();
Module.HEAP32[<any>offset >>> 2] = value;
}
export function setI32 (offset: MemOffset, value: number): void {
assert_int_in_range(<any>value, -0x8000_0000, 0x7FFF_FFFF);
receiveWorkerHeapViews();
Module.HEAP32[<any>offset >>> 2] = value;
}
function autoThrowI52 (error: I52Error) {
if (error === I52Error.NONE)
return;
switch (error) {
case I52Error.NON_INTEGRAL:
throw new Error("value was not an integer");
case I52Error.OUT_OF_RANGE:
throw new Error("value out of range");
default:
throw new Error("unknown internal error");
}
}
/**
* Throws for values which are not 52 bit integer. See Number.isSafeInteger()
*/
export function setI52 (offset: MemOffset, value: number): void {
mono_check(Number.isSafeInteger(value), () => `Value is not a safe integer: ${value} (${typeof (value)})`);
receiveWorkerHeapViews();
const error = cwraps.mono_wasm_f64_to_i52(<any>offset, value);
autoThrowI52(error);
}
/**View on GitHub (pinned to 290d5ab72c)
Solutions
- Round the value before passing: Math.trunc(value) or Math.round(value).
- Validate with Number.isInteger(value) before calling the i52/u52 API.
- If you genuinely need fractions, store them as f64 via setF64 instead.
Example fix
// before Module.setHeapI52(offset, value /* 3.5 */); // after Module.setHeapI52(offset, Math.trunc(value));
Defensive patterns
Strategy: validation
Validate before calling
if (!Number.isInteger(value)) throw new TypeError(`Expected an integer for i52 slot, got ${value}.`); Type guard
function isIntegerNumber(v: unknown): v is number { return typeof v === 'number' && Number.isInteger(v); } Prevention
- Round with Math.trunc/Math.round before writing a 52-bit slot.
- Validate Number.isInteger before calling setI52/setU52 (or setHeapI52/setHeapU52).
- Use setF64 if you need to store fractional values.
When it happens
Trigger: Passing a fractional Number (e.g. 3.5) to setI52/setU52 or the exported setHeapI52/setHeapU52, or any path that converts a double to a 52-bit integer slot when the value is non-integral.
Common situations: Calling the low-level heap helpers (Module.setHeapI52/setHeapU52) with a computed float; feeding an unrounded measurement/index into a 52-bit slot; floating-point math drift producing x.0+epsilon.
Related errors
- value out of range
- ${function_name} must be a Function but was ${typeof fn}
- .NET runtime has failed to start, because too much memory wa
- NotImplementedException: bigint
- NotImplementedException: TypedArray
AI-assisted analysis of dotnet/runtime@290d5ab72c (2026-08-06).
Data as JSON: /api/errors/b2dc987187443ca8.
Report an issue: GitHub.