dotnet/runtime · error · Error
JSObject proxy is not supported for ${jsType} ${value}
Error message
JSObject proxy is not supported for ${jsType} ${value} What it means
The final fallback in marshalCsObjectToCs: the JS value has no GCHandle, typeof is not string/number/boolean/bigint/object-handled, and is not an array/date/error/thenable/span. The current case in practice is typeof === "function": a raw JS function passed where a marshaled object was expected.
Source
Thrown at src/native/libs/System.Runtime.InteropServices.JavaScript.Native/interop/marshal-to-cs.ts:401
|| value instanceof Int8Array
|| value instanceof Uint8ClampedArray
|| value instanceof Uint16Array
|| value instanceof Uint32Array
) {
throw new Error("NotImplementedException: TypedArray");
} else if (isThenable(value)) {
marshalTaskToCs(arg, value);
} else if (value instanceof Span) {
throw new Error("NotImplementedException: Span");
} else if (jsType == "object") {
const jsHandle = getJsHandleFromJSObject(value);
setArgType(arg, MarshalerType.JSObject);
if (BuildConfiguration === "Debug" && Object.isExtensible(value)) {
value[proxyDebugSymbol] = `JS Object with JSHandle ${jsHandle}`;
}
setJsHandle(arg, jsHandle);
} else {
throw new Error(`JSObject proxy is not supported for ${jsType} ${value}`);
}
} else {
assertNotDisposed(value);
if (value instanceof ArraySegment) {
throw new Error("NotImplementedException: ArraySegment. " + jsinteropDoc);
} else if (value instanceof ManagedError) {
setArgType(arg, MarshalerType.Exception);
setGcHandle(arg, gcHandle);
} else if (value instanceof ManagedObject) {
setArgType(arg, MarshalerType.Object);
setGcHandle(arg, gcHandle);
} else {
throw new Error("NotImplementedException " + jsType + ". " + jsinteropDoc);
}
}
}
}
View on GitHub (pinned to 290d5ab72c)
Solutions
- If you intend to pass a callable, declare the C# parameter as a delegate (Action/Func) with the appropriate [JSMarshalAsAttribute<JSType.Function>] so the function marshaler is used.
- Otherwise, serialize the value to a plain object or string before marshaling.
Example fix
// before
[JSImport("globalThis.fns.run")]
static partial void Run(object cb);
Run(callbackFn); // JS function -> error
// after
[JSImport("globalThis.fns.run")]
static partial void Run([JSMarshalAsAttribute<JSType.Function>] Action cb); Defensive patterns
Strategy: type-guard
Validate before calling
function prepare(value: unknown): unknown {
if (typeof value === "function") {
throw new TypeError("Pass a delegate marshaler for callbacks, not object");
}
return value;
} Type guard
const isPlainDataForCsObject = (v: unknown): boolean =>
v === null || v === undefined ||
["string", "number", "boolean"].includes(typeof v) ||
(typeof v === "object" && typeof (v as any) !== "function"); Prevention
- Use delegate/Action parameters for callbacks instead of object.
- Validate interop argument types in a wrapper layer before calling C#.
When it happens
Trigger: Passing a JS function reference to a C# method whose parameter is typed `object` rather than as a delegate/function handle. Also passing exotic host objects whose typeof returns an unsupported category.
Common situations: Trying to send a callback function to C# via an object-typed parameter instead of using a delegate/Action marshaler; passing a Proxy or class constructor where a data object was expected.
Related errors
- JSObject proxy is not supported for ${js_type} ${value}
- NotImplementedException: bigint
- NotImplementedException: TypedArray
- NotImplementedException: Span
- NotImplementedException: ArraySegment. For more information
AI-assisted analysis of dotnet/runtime@290d5ab72c (2026-08-06).
Data as JSON: /api/errors/e7a7388fe6a53cf2.
Report an issue: GitHub.