dotnet/runtime · error · Error
count_or_values must be either an array or a number greater
Error message
count_or_values must be either an array or a number greater than 0
What it means
Thrown by mono_wasm_new_roots when count_or_values is neither an array nor a positive integer. The API accepts either an array of pointers (initializing one root each) or a count (allocating that many zero roots); anything else - zero, negative, NaN, object, string - falls through to the error branch at line 114.
Source
Thrown at src/mono/browser/runtime/roots.ts:114
/**
* 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;
if (Array.isArray(count_or_values)) {
result = new Array(count_or_values.length);
for (let i = 0; i < result.length; i++)
result[i] = mono_wasm_new_root(count_or_values[i]);
} else if ((count_or_values | 0) > 0) {
result = new Array(count_or_values);
for (let i = 0; i < result.length; i++)
result[i] = mono_wasm_new_root();
} else {
throw new Error("count_or_values must be either an array or a number greater than 0");
}
return result;
}
/**
* Releases 1 or more root or root buffer objects.
* Multiple objects may be passed on the argument list.
* 'undefined' may be passed as an argument so it is safe to call this method from finally blocks
* even if you are not sure all of your roots have been created yet.
* @param {... WasmRoot} roots
*/
export function mono_wasm_release_roots (...args: WasmRoot<any>[]): void {
for (let i = 0; i < args.length; i++) {
if (is_nullish(args[i]))
continue;
args[i].release();View on GitHub (pinned to 60108ba66e)
Solutions
- If you want N roots, ensure N is a positive integer before calling.
- If you want initialized roots, pass an array of numeric pointers.
- Guard: branch on Array.isArray / Number.isInteger(x) && x > 0 at the call site and skip when nothing is needed.
Example fix
// before const roots = mono_wasm_new_roots(values.length); // throws if values is empty // after const roots = values.length > 0 ? mono_wasm_new_roots(values.length) : [];
Defensive patterns
Strategy: type-guard
Validate before calling
function newRootsSafe(count_or_values: number | unknown[]) {
if (Array.isArray(count_or_values)) return mono_wasm_new_roots(count_or_values);
if (typeof count_or_values === 'number' && Number.isInteger(count_or_values) && count_or_values > 0)
return mono_wasm_new_roots(count_or_values);
return [];
} Type guard
function isRootsArg(a: unknown): a is number | unknown[] {
return Array.isArray(a) || (typeof a === 'number' && Number.isInteger(a) && a > 0);
} Prevention
- Handle the empty-count case in the caller instead of forwarding 0.
- Use Array.isArray plus Number.isInteger checks at the boundary.
- Avoid floats - they truncate to 0 via |0 and silently fail.
When it happens
Trigger: Calling mono_wasm_new_roots(0), mono_wasm_new_roots(-3), mono_wasm_new_roots(NaN), or mono_wasm_new_roots(someObject) (non-array, non-number). Note (count_or_values | 0) > 0 means fractional/zero values fail.
Common situations: Passing a length computed from an empty collection; passing a JS object instead of an array; passing a float that truncates to 0 via |0; a variable that is sometimes undefined.
Related errors
- capacity >= 1
- value must be an address in the managed heap
- 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/b0583f3726b8c497.
Report an issue: GitHub.