dotnet/runtime · error · Error

NotImplementedException: Span

Error message

NotImplementedException: Span

What it means

A JS value that is an instance of the interop Span type reached marshalCsObjectToCs in a context where the value has no managed gcHandle (i.e. it was not a Span handed back from C# to JS and then returned). Span is only meant to be marshaled via the explicit Span marshaler path (_marshalSpanToCs), not through the generic object converter.

Solutions

  1. Type the C# parameter/return as Span<T> (or the matching ref struct) so the value is routed through _marshalSpanToCs instead of the object marshaler.
  2. Do not pass Span instances through object-typed interop boundaries; keep them on explicitly Span-typed signatures.
  3. If you only need the bytes, copy the Span's contents into a Uint8Array/byte[] before crossing the object boundary.

Example fix

// before - C#
[JSImport("consume", "m")]
static partial void Consume([MarshalAs(typeof(object))] object span);

// after
[JSImport("consume", "m")]
static partial void Consume(Span<byte> span);
Defensive patterns

Strategy: type-guard

Validate before calling

// Don't pass a Span through an object-typed boundary; copy out the bytes.
import { Span } from "./marshaled-types";

function spanToBytes(s: Span): Uint8Array | null {
  if (!(s instanceof Span)) return null;
  return s.slice() as Uint8Array; // independent copy safe to marshal as byte[]
}

Type guard

function isSpan(v: unknown): boolean {
  return v instanceof Span;
}

Try / catch

null

Prevention

When it happens

Trigger: Constructing or obtaining a Span object in JS (e.g. from an earlier interop call that returned one) and then passing it back through a parameter/return typed as object or JSObject rather than as an explicit Span-typed marshaled argument.

Common situations: Storing a Span returned by one JSImport and passing it into another JSImport whose parameter is typed object; mixing Span with generic object marshaling signatures.

Related errors


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

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