dotnet/runtime · error · Error

NotImplementedException: Span

Error message

NotImplementedException: Span

What it means

marshal_cs_object_to_cs throws when value instanceof Span but the C# parameter is the generic object marshaler. Span uses its own marshaler (_marshal_span_to_cs) which is selected only when the C# parameter is strongly typed as Span<T>; through the object path it is unsupported.

Source

Thrown at src/mono/browser/runtime/marshal-to-cs.ts:421

            } else if (value instanceof Float32Array) {
                marshal_array_to_cs_impl(arg, value, MarshalerType.Single);
            } else if (value instanceof Float64Array) {
                marshal_array_to_cs_impl(arg, value, MarshalerType.Double);
            } else if (value instanceof Int32Array) {
                marshal_array_to_cs_impl(arg, value, MarshalerType.Int32);
            } else if (Array.isArray(value)) {
                marshal_array_to_cs_impl(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)) {
                marshal_task_to_cs(arg, value);
            } else if (value instanceof Span) {
                throw new Error("NotImplementedException: Span");
            } else if (js_type == "object") {
                const js_handle = mono_wasm_get_js_handle(value);
                set_arg_type(arg, MarshalerType.JSObject);
                if (BuildConfiguration === "Debug" && Object.isExtensible(value)) {
                    value[proxy_debug_symbol] = `JS Object with JSHandle ${js_handle}`;
                }
                set_js_handle(arg, js_handle);
            } else {
                throw new Error(`JSObject proxy is not supported for ${js_type} ${value}`);
            }
        } else {
            assert_not_disposed(value);
            if (value instanceof ArraySegment) {
                throw new Error("NotImplementedException: ArraySegment. " + jsinteropDoc);
            } else if (value instanceof ManagedError) {
                set_arg_type(arg, MarshalerType.Exception);
                set_gc_handle(arg, gc_handle);
            } else if (value instanceof ManagedObject) {

View on GitHub (pinned to 290d5ab72c)

Solutions

  1. Declare the C# parameter as the concrete Span<T> (byte, int, double, or float element).
  2. Copy the Span into a supported array (Uint8Array/Int32Array/Float32Array/Float64Array) and pass that to an object/array-typed parameter.

Example fix

// C# before
[JSExport] public static void Take(object v) { }
// JS: dotnet.jsExports.Take(spanFromCs); // throws
// C# after
[JSExport] public static void Take(Span<byte> v) { }
Defensive patterns

Strategy: type-guard

Validate before calling

if (value && value instanceof Span) throw new TypeError('Pass a Span only to a C# Span<T> parameter, not object/JSObject.');

Type guard

function isSpan(v: unknown): boolean { return v != null && typeof v === 'object' && v instanceof Span; }

Prevention

When it happens

Trigger: Passing a JS Span object (one returned from a prior C# Span<T> call) to a C# [JSExport] parameter typed as object/JSObject rather than Span<T>.

Common situations: Round-tripping a Span through a generic API; passing a memory view to a loosely-typed method.

Related errors


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