dotnet/runtime · error · Error

NotImplementedException ${elementType}. ${jsinteropDoc}

Error message

NotImplementedException ${elementType}. ${jsinteropDoc}

What it means

Thrown by _marshalArrayToJs_impl at the final else branch when marshaling a C# array back to JS whose elementType is not String/Object/JSObject/Byte/Int32/Double/Single. The reverse direction of marshalArrayToCsImpl: only those seven element kinds have a buffer-view materializer, so anything else is rejected rather than producing garbage.

Source

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

        }
    } else if (elementType == MarshalerType.Byte) {
        const bufferOffset = fixupPointer(bufferPtr, 0);
        const sourceView = dotnetApi.localHeapViewU8().subarray(bufferOffset, bufferOffset + length);
        result = sourceView.slice();//copy
    } else if (elementType == MarshalerType.Int32) {
        const bufferOffset = fixupPointer(bufferPtr, 2);
        const sourceView = dotnetApi.localHeapViewI32().subarray(bufferOffset, bufferOffset + length);
        result = sourceView.slice();//copy
    } else if (elementType == MarshalerType.Double) {
        const bufferOffset = fixupPointer(bufferPtr, 3);
        const sourceView = dotnetApi.localHeapViewF64().subarray(bufferOffset, bufferOffset + length);
        result = sourceView.slice();//copy
    } else if (elementType == MarshalerType.Single) {
        const bufferOffset = fixupPointer(bufferPtr, 2);
        const sourceView = dotnetApi.localHeapViewF32().subarray(bufferOffset, bufferOffset + length);
        result = sourceView.slice();//copy
    } else {
        throw new Error(`NotImplementedException ${elementType}. ${jsinteropDoc}`);
    }
    Module._free(<any>bufferPtr);
    return result;
}

function _marshalSpanToJs(arg: JSMarshalerArgument, elementType?: MarshalerType): Span {
    dotnetAssert.check(!!elementType, "Expected valid elementType parameter");

    const bufferPtr = getArgIntptr(arg);
    const length = getArgLength(arg);
    let result: Span | null = null;
    if (elementType == MarshalerType.Byte) {
        result = new Span(<any>bufferPtr, length, MemoryViewType.Byte);
    } else if (elementType == MarshalerType.Int32) {
        result = new Span(<any>bufferPtr, length, MemoryViewType.Int32);
    } else if (elementType == MarshalerType.Double) {
        result = new Span(<any>bufferPtr, length, MemoryViewType.Double);
    } else if (elementType == MarshalerType.Single) {

View on GitHub (pinned to 60108ba66e)

Solutions

  1. Change the C# return element type to a supported one: byte, int, double, float, string, object, or JSObject.
  2. If you must return 16-bit values, return int[] and downcast on the JS side.
  3. Rebuild and redeploy the runtime + assemblies together so the element-type table is consistent.

Example fix

// before (C#)
[JSExport] public static short[] GetIds() => new short[]{1,2,3}; // JS throws NotImplementedException Int16

// after (C#)
[JSExport] public static int[] GetIds() => new int[]{1,2,3}; // Int32 supported
Defensive patterns

Strategy: validation

Validate before calling

const SUPPORTED = new Set(['Byte','Int32','Double','Single','String','Object','JSObject']);

// Validate at the C# design level before exposing the export:
//   [JSExport] static int[] Get() => ...   // OK
//   [JSExport] static short[] Get() => ... // will throw - avoid
if (!SUPPORTED.has(returnedElementType)) {
  throw new Error('Refusing to expose an export returning an unsupported array element type');
}

Try / catch

try {
  const arr = await csharpExport();
} catch (e) {
  if (e instanceof Error && e.message.startsWith('NotImplementedException ')) {
    // The C# export returned an array of an unsupported element type.
    throw new TypeError('C# export must return byte[]/int[]/double[]/float[]/string[]/object[]/JSObject[]', { cause: e });
  }
  throw e;
}

Prevention

When it happens

Trigger: A [JSExport] (or [JSInvokable] from the JS perspective) C# method returns an array of an unsupported element type (Int16[], char[], long[], enum[], Nullable<T>[], etc.) and the marshaler tries to convert the returned buffer into a JS array. Hit at marshal-to-js.ts:470.

Common situations: Returning short[]/char[]/nint[] from a C# export and reading the result in JS. Using an enum-typed array. Runtime/loader version skew where the C# assembly was rebuilt with a new return type but the JS marshaler was not.

Related errors


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