dotnet/runtime · error · Error
JSObject proxy is not supported for ${js_type} ${value}
Error message
JSObject proxy is not supported for ${js_type} ${value} What it means
The final else in marshal_cs_object_to_cs fires when the JS value's typeof is not string, number, bigint, boolean, or object. In practice this means a Symbol or a Function passed where the C# parameter is object/JSObject, neither of which has an object-marshaler mapping.
Source
Thrown at src/mono/browser/runtime/marshal-to-cs.ts:430
|| value instanceof Int8Array
|| value instanceof Uint8ClampedArray
|| value instanceof Uint16Array
|| value instanceof Uint32Array
) {
throw new Error("NotImplementedException: TypedArray");
} else if (isThenable(value)) {
marshal_task_to_cs(arg, value);
} else if (value instanceof Span) {
throw new Error("NotImplementedException: Span");
} else if (js_type == "object") {
const js_handle = mono_wasm_get_js_handle(value);
set_arg_type(arg, MarshalerType.JSObject);
if (BuildConfiguration === "Debug" && Object.isExtensible(value)) {
value[proxy_debug_symbol] = `JS Object with JSHandle ${js_handle}`;
}
set_js_handle(arg, js_handle);
} else {
throw new Error(`JSObject proxy is not supported for ${js_type} ${value}`);
}
} else {
assert_not_disposed(value);
if (value instanceof ArraySegment) {
throw new Error("NotImplementedException: ArraySegment. " + jsinteropDoc);
} else if (value instanceof ManagedError) {
set_arg_type(arg, MarshalerType.Exception);
set_gc_handle(arg, gc_handle);
} else if (value instanceof ManagedObject) {
set_arg_type(arg, MarshalerType.Object);
set_gc_handle(arg, gc_handle);
} else {
throw new Error("NotImplementedException " + js_type + ". " + jsinteropDoc);
}
}
}
}
View on GitHub (pinned to 290d5ab72c)
Solutions
- For functions, pass them through a parameter typed to accept a JS function proxy, or wrap them in an object whose handle can be obtained.
- Convert Symbols to strings; convert functions to a serializable representation or invoke them in JS and pass the result.
- Type the C# parameter to match the actual JS value kind rather than object.
Example fix
// before
dotnet.jsExports.Take(Symbol('id')); // throws
// after
dotnet.jsExports.Take('id'); // pass a string Defensive patterns
Strategy: type-guard
Validate before calling
const t = typeof value;
if (t === 'symbol' || t === 'function') {
throw new TypeError(`${t} is not supported by the object marshaler; convert to a supported type.`);
} Type guard
function isUnsupportedObjectKind(v: unknown): boolean { const t = typeof v; return t === 'symbol' || t === 'function'; } Prevention
- Do not pass Symbols or Functions to object/JSObject C# parameters.
- Convert Symbols to strings; invoke functions in JS and pass their results.
- Type C# parameters to match the actual JS value kind.
When it happens
Trigger: Passing a JS Symbol or a Function to a C# [JSExport] parameter typed as object/JSObject.
Common situations: Sending a callback function or a Symbol to a generic object parameter expecting a data object; forgetting to wrap a function in a JSObject-backed holder.
Related errors
- NotImplementedException: bigint
- NotImplementedException: TypedArray
- JSObject proxy is not supported for ${jsType} ${value}
- ${function_name} must be a Function but was ${typeof fn}
- NotImplementedException: Span
AI-assisted analysis of dotnet/runtime@290d5ab72c (2026-08-06).
Data as JSON: /api/errors/f2b01c1111be44c9.
Report an issue: GitHub.