dotnet/runtime · error · Error

Argument to stringToInternedMonoStringRoot must be a string

Error message

Argument to stringToInternedMonoStringRoot must be a string but was ${string}

What it means

Thrown by stringToInternedMonoStringRoot when, after routing through the symbol/string branches, the resulting text variable is still not a string. In practice the symbol branch falls back to '<unknown Symbol>' so this is a defensive guard; it fires only if the input is neither a string nor a valid symbol and the routing logic did not assign text.

Source

Thrown at src/mono/browser/runtime/strings.ts:210

    }
}

function stringToInternedMonoStringRoot (string: string | symbol, result: WasmRoot<MonoString>): void {
    let text: string | undefined;
    if (typeof (string) === "symbol") {
        text = string.description;
        if (typeof (text) !== "string")
            text = Symbol.keyFor(string);
        if (typeof (text) !== "string")
            text = "<unknown Symbol>";
    } else if (typeof (string) === "string") {
        text = string;
    }

    if (typeof (text) !== "string") {
        // eslint-disable-next-line @typescript-eslint/ban-ts-comment
        // @ts-ignore
        throw new Error(`Argument to stringToInternedMonoStringRoot must be a string but was ${string}`);
    }

    if ((text.length === 0) && _empty_string_ptr) {
        result.set(_empty_string_ptr);
        return;
    }

    const ptr = interned_js_string_table.get(text);
    if (ptr) {
        result.set(ptr);
        return;
    }

    stringToMonoStringNewRoot(text, result);
    storeStringInInternTable(text, result, true);
}

function storeStringInInternTable (string: string, root: WasmRoot<MonoString>, internIt: boolean): void {

View on GitHub (pinned to 60108ba66e)

Solutions

  1. Do not call stringToInternedMonoStringRoot directly; rely on stringToMonoStringRoot which type-checks first.
  2. Ensure symbols passed in have a usable description or are registered with Symbol.keyFor so text resolves to a string.
  3. If extending accepted types in this helper, make sure every branch assigns a string to text.
Defensive patterns

Strategy: validation

Validate before calling

// Do not call stringToInternedMonoStringRoot directly; go through stringToMonoStringRoot,
// which pre-filters non-string/non-symbol values.
stringToMonoStringRoot(input, root);

Type guard

function isStringOrSymbol(v: unknown): v is string | symbol {
  return typeof v === 'string' || typeof v === 'symbol';
}

Prevention

When it happens

Trigger: Calling stringToInternedMonoStringRoot with a value that is neither string nor symbol, in a code path where the upstream typeof checks did not already redirect. Reachable if the function is invoked directly (it is not exported but is called by stringToMonoStringRoot for symbols/empty strings) with an unexpected type.

Common situations: Internal misuse of the private interned-string helper; a future refactor that adds a new accepted type but forgets to assign text; extremely rare in normal usage because stringToMonoStringRoot pre-filters inputs.

Related errors


AI-assisted analysis of dotnet/runtime@60108ba66e (2026-08-10). Data as JSON: /api/errors/ff68445ccc0f8d26. Report an issue: GitHub.