{"record":{"id":"df964d4c90806893","repo":"dotnet/runtime","slug":"notimplementedexception-span","errorCode":null,"errorMessage":"NotImplementedException: Span","messagePattern":"NotImplementedException: Span","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"src/mono/browser/runtime/marshal-to-cs.ts","lineNumber":421,"sourceCode":"            } else if (value instanceof Float32Array) {\n                marshal_array_to_cs_impl(arg, value, MarshalerType.Single);\n            } else if (value instanceof Float64Array) {\n                marshal_array_to_cs_impl(arg, value, MarshalerType.Double);\n            } else if (value instanceof Int32Array) {\n                marshal_array_to_cs_impl(arg, value, MarshalerType.Int32);\n            } else if (Array.isArray(value)) {\n                marshal_array_to_cs_impl(arg, value, MarshalerType.Object);\n            } else if (value instanceof Int16Array\n                || value instanceof Int8Array\n                || value instanceof Uint8ClampedArray\n                || value instanceof Uint16Array\n                || value instanceof Uint32Array\n            ) {\n                throw new Error(\"NotImplementedException: TypedArray\");\n            } else if (isThenable(value)) {\n                marshal_task_to_cs(arg, value);\n            } else if (value instanceof Span) {\n                throw new Error(\"NotImplementedException: Span\");\n            } else if (js_type == \"object\") {\n                const js_handle = mono_wasm_get_js_handle(value);\n                set_arg_type(arg, MarshalerType.JSObject);\n                if (BuildConfiguration === \"Debug\" && Object.isExtensible(value)) {\n                    value[proxy_debug_symbol] = `JS Object with JSHandle ${js_handle}`;\n                }\n                set_js_handle(arg, js_handle);\n            } else {\n                throw new Error(`JSObject proxy is not supported for ${js_type} ${value}`);\n            }\n        } else {\n            assert_not_disposed(value);\n            if (value instanceof ArraySegment) {\n                throw new Error(\"NotImplementedException: ArraySegment. \" + jsinteropDoc);\n            } else if (value instanceof ManagedError) {\n                set_arg_type(arg, MarshalerType.Exception);\n                set_gc_handle(arg, gc_handle);\n            } else if (value instanceof ManagedObject) {","sourceCodeStart":403,"sourceCodeEnd":439,"githubUrl":"https://github.com/dotnet/runtime/blob/60108ba66eb7d1d12f595480091b4ad80a24b172/src/mono/browser/runtime/marshal-to-cs.ts#L403-L439","documentation":"Thrown by marshal_cs_object_to_cs() when a value that is instanceof Span (but does not have a C# gc_handle) is passed to a C# 'object' parameter. Span objects are created by the runtime when marshaling C# Span<T> to JS (via _marshal_span_to_js), but they are NOT registered as managed proxies (no setup_managed_proxy call). If you then try to pass such a Span back to C# as an 'object', the object marshaler does not know how to handle it. The proper way to pass a Span back is to declare the C# parameter as Span<T> with the correct element type.","triggerScenarios":"Receiving a Span<T> from a C# JSExport (which creates a JS-side Span wrapper), then passing it to another C# method whose parameter is 'object' instead of Span<T>. The gc_handle is undefined (Span is not a managed proxy), and instanceof Span is true at line 420.","commonSituations":"Chaining interop calls where a Span from one method is forwarded to another method with a different signature. Using a loosely-typed 'object' parameter to accept any value including a Span.","solutions":["Declare the C# receiving parameter as Span<T> (e.g., Span<byte>) with the matching element type so the _marshal_span_to_cs marshaler is used instead of the object marshaler.","If you must use 'object', convert the Span to a TypedArray or byte[] before passing it: use the Span's underlying buffer.","Keep the Span reference and pass it only to methods with explicit Span<T> parameters.","Copy the Span data into a new Uint8Array/Int32Array/etc. and pass that array to the object parameter."],"exampleFix":"// before (Span passed to object parameter)\n// C#: [JSExport] public static void Consume(object data) { }\n// JS:  const span = GetSpanFromCSharp(); // returns Span\n//      Consume(span); // throws NotImplementedException: Span\n\n// after (use Span<byte> parameter)\n// C#: [JSExport] public static void Consume(Span<byte> data) { }\n// JS:  Consume(span); // works via _marshal_span_to_cs","handlingStrategy":"type-guard","validationCode":"// Check if value is a Span before passing to object parameter\nfunction isSpan(value: any): boolean {\n  return value !== null && typeof value === 'object' && value.constructor && value.constructor.name === 'Span';\n}\n\nif (isSpan(myValue)) {\n  // extract data or use Span<T> parameter instead\n  const bytes = new Uint8Array(myValue._pointer, 0, myValue.length);\n}","typeGuard":"function isSpanLike(value: unknown): boolean {\n  return value !== null && typeof value === 'object'\n    && '_pointer' in (value as any)\n    && 'length' in (value as any)\n    && '_viewType' in (value as any);\n}","tryCatchPattern":null,"preventionTips":["Never pass a Span to a C# 'object' parameter; always use Span<T>.","If you must pass Span data through a generic API, copy it to a Uint8Array first.","Track which values are Span instances and route them to the correct typed parameter."],"tags":["marshaling","span","type-mismatch","interop"],"backgroundTag":null,"analyzedSha":"60108ba66eb7d1d12f595480091b4ad80a24b172","analyzedAt":"2026-08-10T18:54:11.478Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}