dotnet/runtime · error · Error
value must be an address in the managed heap
Error message
value must be an address in the managed heap
What it means
Thrown by mono_wasm_new_root when an initial value is supplied that is not undefined and not a number. Managed-heap addresses are represented as numeric pointers; passing an object, string, or other type as the initial value cannot be stored as a managed pointer, so it is rejected.
Source
Thrown at src/mono/browser/runtime/roots.ts:86
* The result object has get() and set(value) methods, along with a .value property.
* When you are done using the root you must call its .release() method.
*/
export function mono_wasm_new_root<T extends MonoObject> (value: T | undefined = undefined): WasmRoot<T> {
if (WasmEnableThreads && runtimeHelpers.disableManagedTransition) throw new Error("External roots are not supported in multithreaded mode");
let result: WasmRoot<T>;
if (_scratch_root_free_instances.length > 0) {
result = _scratch_root_free_instances.pop()!;
} else {
const index = _mono_wasm_claim_scratch_index();
const buffer = _scratch_root_buffer;
result = new WasmJsOwnedRoot(buffer!, index);
}
if (value !== undefined) {
if (typeof (value) !== "number")
throw new Error("value must be an address in the managed heap");
result.set(value);
} else {
result.set(<any>0);
}
return result;
}
/**
* Allocates 1 or more temporary roots, accepting either a number of roots or an array of pointers.
* mono_wasm_new_roots(n): returns an array of N zero-initialized roots.
* mono_wasm_new_roots([a, b, ...]) returns an array of new roots initialized with each element.
* Each root must be released with its release method, or using the mono_wasm_release_roots API.
*/
export function mono_wasm_new_roots<T extends MonoObject> (count_or_values: number | T[]): WasmRoot<T>[] {
let result;
View on GitHub (pinned to 60108ba66e)
Solutions
- Pass a numeric managed-heap address, or pass undefined for zero-initialization.
- If you have a WasmRoot, use root.value or root.address to get the numeric pointer first.
- Add a typeof check at the call site to fail with a clearer upstream message.
Example fix
// before const r = mono_wasm_new_root(otherRoot); // otherRoot is an object // after const r = mono_wasm_new_root(otherRoot.value); // numeric pointer
Defensive patterns
Strategy: type-guard
Validate before calling
function newRootSafe(value?: number) {
if (value !== undefined && typeof value !== 'number') {
throw new TypeError('initial value must be a numeric managed pointer or undefined');
}
return mono_wasm_new_root(value);
} Type guard
function isManagedPointer(v: unknown): v is number {
return v === undefined || (typeof v === 'number' && Number.isFinite(v));
} Prevention
- Pass undefined rather than 0 for explicit zero-initialization if unsure.
- When you already hold a root, dereference with .value before forwarding.
- Type call sites strictly as (value?: number).
When it happens
Trigger: Calling mono_wasm_new_root(someObject), mono_wasm_new_root('a string'), or any call where the second argument is defined but typeof value !== 'number'. Passing undefined is allowed (zero-initializes the root).
Common situations: Accidentally passing a JS wrapper or WasmRoot instance instead of its .value/.address; a refactor that changed the parameter type without updating call sites; passing a managed object handle object rather than its numeric id.
Related errors
- capacity >= 1
- count_or_values must be either an array or a number greater
- address must be a location in the native heap
- index out of range
- Expected runtimeOptions to be an array of strings
AI-assisted analysis of dotnet/runtime@60108ba66e (2026-08-10).
Data as JSON: /api/errors/6e1195567f02d976.
Report an issue: GitHub.