dotnet/runtime · error · Error

NotImplementedException: bigint

Error message

NotImplementedException: bigint

What it means

marshalCsObjectToCs handles a JS value of type 'bigint' when the value has no jsOwnedGcHandleSymbol (i.e. it is a raw bigint being marshaled as a generic object, not a managed Int64). The marshaler does not attempt to coerce arbitrary-precision bigints into a .NET object and throws NotImplementedException. Use a typed Int64/Int52 parameter or BigInt64 marshaler instead.

Solutions

  1. Declare the C# signature with an explicit long/Int64 (or long[]) parameter/return and the BigInt64 marshaler so the value goes through _marshalBigint64ToCs instead of the object path.
  2. If the value may exceed Int64 range, convert it to a string in JS and parse on the C# side (long.Parse / BigInteger.Parse).
  3. Avoid returning raw bigints from interop functions typed as object; pick a concrete primitive or JSObject marshaling.

Example fix

// before - C#
[return: MarshalAs(typeof(object))]
[JSImport("big", "m")]
static partial object Big(); // JS returns BigInt(123) -> throws

// after
[return: MarshalAs(typeof(long))]
[JSImport("big", "m")]
static partial long Big(); // routed through BigInt64 marshaler
Defensive patterns

Strategy: type-guard

Validate before calling

// On the JS side, avoid returning a raw bigint through an object-typed boundary.
function safeReturn(value: unknown): unknown {
  if (typeof value === "bigint") {
    // marshal as Int64-friendly value or string
    return value.toString(); // parse with long.Parse / BigInteger.Parse on C# side
  }
  return value;
}

Type guard

function isBigint(v: unknown): v is bigint {
  return typeof v === "bigint";
}

Try / catch

null

Prevention

When it happens

Trigger: A JS function invoked from C# via JSImport returns or passes a JS bigint in a position typed as `object`/JSObject (marshalCsObjectToCs path) rather than a parameter explicitly marshaled as BigInt64/Int64. For example returning BigInt(...) from a JS function whose [return: ...] is object.

Common situations: Returning BigInt(...) from a JS interop function while the C# side declares the return as object or lacks the explicit [return: MarshalAs(... BigInt64)]; passing a bigint into a params object[] array; third-party JS lib returning bigints through interop.

Related errors


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

Appendix: source

Thrown at src/native/libs/System.Runtime.InteropServices.JavaScript.Native/interop/marshal-to-cs.ts:363

}

export function marshalCsObjectToCs(arg: JSMarshalerArgument, value: any): void {
    if (value === undefined || value === null) {
        setArgType(arg, MarshalerType.None);
        setArgProxyContext(arg);
    } else {
        const gcHandle = value[jsOwnedGcHandleSymbol];
        const jsType = typeof (value);
        if (gcHandle === undefined) {
            if (jsType === "string" || jsType === "symbol") {
                setArgType(arg, MarshalerType.String);
                _marshalStringToCsImpl(arg, value);
            } else if (jsType === "number") {
                setArgType(arg, MarshalerType.Double);
                setArgF64(arg, value);
            } else if (jsType === "bigint") {
                // we do it because not all bigint values could fit into Int64
                throw new Error("NotImplementedException: bigint");
            } else if (jsType === "boolean") {
                setArgType(arg, MarshalerType.Boolean);
                setArgBool(arg, value);
            } else if (value instanceof Date) {
                setArgType(arg, MarshalerType.DateTime);
                setArgDate(arg, value);
            } else if (value instanceof Error) {
                marshalExceptionToCs(arg, value);
            } else if (value instanceof Uint8Array) {
                marshalArrayToCsImpl(arg, value, MarshalerType.Byte);
            } else if (value instanceof Float64Array) {
                marshalArrayToCsImpl(arg, value, MarshalerType.Double);
            } else if (value instanceof Float32Array) {
                marshalArrayToCsImpl(arg, value, MarshalerType.Single);
            } else if (value instanceof Int32Array) {
                marshalArrayToCsImpl(arg, value, MarshalerType.Int32);
            } else if (Array.isArray(value)) {
                marshalArrayToCsImpl(arg, value, MarshalerType.Object);

View on GitHub (pinned to 60108ba66e)