{"record":{"id":"6d632610a69b8595","repo":"dotnet/runtime","slug":"expected-string-argument-got-typeof-string","errorCode":null,"errorMessage":"Expected string argument, got ${typeof(string)}","messagePattern":"Expected string argument, got (.+?)","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"src/mono/browser/runtime/strings.ts","lineNumber":174,"sourceCode":"            result = mono_wasm_empty_string;\n    }\n\n    if (result === undefined)\n        throw new Error(`internal error when decoding string at location ${root.value}`);\n\n    return result;\n}\n\nexport function stringToMonoStringRoot (string: string, result: WasmRoot<MonoString>): void {\n    if (WasmEnableThreads) return;\n    result.clear();\n\n    if (string === null)\n        return;\n    else if (typeof (string) === \"symbol\")\n        stringToInternedMonoStringRoot(string, result);\n    else if (typeof (string) !== \"string\")\n        throw new Error(\"Expected string argument, got \" + typeof (string));\n    else if (string.length === 0)\n        // Always use an interned pointer for empty strings\n        stringToInternedMonoStringRoot(string, result);\n    else {\n        // Looking up large strings in the intern table will require the JS runtime to\n        //  potentially hash them and then do full byte-by-byte comparisons, which is\n        //  very expensive. Because we can not guarantee it won't happen, try to minimize\n        //  the cost of this and prevent performance issues for large strings\n        if (string.length <= 256) {\n            const interned = interned_js_string_table.get(string);\n            if (interned) {\n                result.set(interned);\n                return;\n            }\n        }\n\n        stringToMonoStringNewRoot(string, result);\n    }","sourceCodeStart":156,"sourceCodeEnd":192,"githubUrl":"https://github.com/dotnet/runtime/blob/60108ba66eb7d1d12f595480091b4ad80a24b172/src/mono/browser/runtime/strings.ts#L156-L192","documentation":"Thrown by stringToMonoStringRoot when the input is not null, not a symbol, and not a string. The function converts a JS value to a Mono string root; only string, symbol, and null are accepted, and any other type (number, object, boolean, undefined) is rejected at line 173-174.","triggerScenarios":"Calling stringToMonoStringRoot(123), stringToMonoStringRoot({}), stringToMonoStringRoot(true), or any non-string non-symbol non-null value. Null is allowed (early return), symbols are routed to the interned path.","commonSituations":"Interop code passing the wrong JS type into string conversion; an untyped binding that receives arbitrary values; a refactor where a value field changed from string to object without updating the call site.","solutions":["Coerce to string before calling: String(value) (or value == null ? null : String(value)).","Type-narrow at the call site: branch on typeof value and only call stringToMonoStringRoot for 'string'/'symbol'/'object(null)'.","Fix the upstream binding so it always supplies a string for string-typed parameters."],"exampleFix":"// before\nstringToMonoStringRoot(maybeNumber, root);\n// after\nstringToMonoStringRoot(maybeNumber == null ? null : String(maybeNumber), root);","handlingStrategy":"type-guard","validationCode":"function toStringOrNullOrThrow(v: unknown): string | null {\n  if (v === null) return null;\n  if (typeof v === 'string' || typeof v === 'symbol') return v as string | symbol;\n  throw new TypeError(`Expected string, got ${typeof v}`);\n}","typeGuard":"function isStringLike(v: unknown): v is string | symbol | null {\n  return v === null || typeof v === 'string' || typeof v === 'symbol';\n}","tryCatchPattern":null,"preventionTips":["Always coerce non-string values with String() at the interop boundary.","Type interop string parameters as string strictly.","Unit-test the binding with each primitive type to catch regressions."],"tags":["strings","validation","argument-error","interop","typescript"],"backgroundTag":null,"analyzedSha":"60108ba66eb7d1d12f595480091b4ad80a24b172","analyzedAt":"2026-08-10T18:54:11.478Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}