dotnet/runtime · error · Error

NotImplementedException: Span

Error message

NotImplementedException: Span

What it means

Thrown by marshalCsObjectToCs when the value is an instance of the runtime's internal Span type while being marshaled through the generic object marshaler. Span instances are designed for round-trip only (created by C# and returned to JS), not for ad-hoc construction and passing back as object.

Source

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

            } 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);
            } else if (value instanceof Int16Array
                || 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) {

View on GitHub (pinned to 290d5ab72c)

Solutions

  1. Declare the C# parameter/return as Span<T> (e.g. Span<byte>) so the dedicated span marshaler is selected.
  2. Copy the span contents into a supported array (span.slice() / copyTo) and pass the array through the object marshaler.

Example fix

// before
static partial void Process(object value); // passing a Span<byte>

// after
static partial void Process(Span<byte> value);
Defensive patterns

Strategy: validation

Validate before calling

// Don't push a Span through the object marshaler
function prepare(value: unknown): unknown {
    if (value && typeof value === "object" && "slice" in value && "_pointer" in value) {
        // it's a runtime Span<T>; copy out instead
        return (value as any).slice();
    }
    return value;
}

Type guard

const isSpanLike = (v: unknown): boolean =>
    !!v && typeof v === "object" &&
    "_pointer" in (v as any) && typeof (v as any).slice === "function";

Prevention

When it happens

Trigger: A JS function imported into C# with an `object` return/parameter type returns or receives a Span<T> object that the runtime created earlier, but the parameter is declared as plain object instead of Span<T>.

Common situations: Holding a Span<T> returned from one C# call and passing it into another C# method whose signature uses `object` instead of `Span<T>`/`Span<byte>`.

Related errors


AI-assisted analysis of dotnet/runtime@290d5ab72c (2026-08-06). Data as JSON: /api/errors/2730c3e70026a511. Report an issue: GitHub.