dotnet/runtime · error · Error

JSObject proxy is not supported for

Error message

JSObject proxy is not supported for ${jsType} ${value}

What it means

In marshalCsObjectToCs, after handling primitives, Date, Error, known typed arrays, arrays, thenables, Span, and plain objects, the final else branch throws for any remaining JS type. In practice this is reached for values whose typeof is 'function' (a raw function passed where object marshaling is expected) because functions are not thenable and not otherwise matched in the gcHandle===undefined branch.

Solutions

  1. Type the C# parameter as the appropriate delegate (Action<...> / Func<...>) so it is routed through _marshalFunctionToCs instead of the object marshaler.
  2. If you genuinely need to pass a callable to C#, wrap it so it is marshaled as a JSObject or a typed delegate, not as a bare object.
  3. Avoid returning bare functions from interop methods typed as object; use a concrete delegate return type.

Example fix

// before - C#
[JSImport("setCb", "m")]
static partial void SetCallback([MarshalAs(typeof(object))] object cb);

// after
[JSImport("setCb", "m")]
static partial void SetCallback(Action<int> cb);
Defensive patterns

Strategy: type-guard

Validate before calling

// Avoid passing a raw function through an object-typed boundary.
function wrapCallback(fn: (...args: any[]) => any): object {
  // return an object holder so it marshals as JSObject, or type the C# side as a delegate
  return { invoke: fn } as object;
}

Type guard

function isPlainFunction(v: unknown): boolean {
  return typeof v === "function";
}

Try / catch

null

Prevention

When it happens

Trigger: Passing a JS function (callback) to a JSImport parameter that is typed as object/JSObject rather than as a delegate (Action/Func) marshaler; or returning a function from a JSImport whose return is typed object.

Common situations: Passing a callback where the C# signature expects object; forgetting to type a callback parameter as the right delegate marshaler so it falls into the object path.

Related errors


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

Appendix: 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 60108ba66e)