Repository navigation
NativeAOT MethodInvoker.Invoke(object, Span<object>) throws InvalidOperationException instead of TargetParameterCountException for a wrong argument count on an open generic method #136102
Description
Description
MethodInvoker.Invoke(object?, Span<object?>) with the wrong number of arguments for a method of an open generic type or a generic method definition throws TargetParameterCountException on CoreCLR and InvalidOperationException on NativeAOT. The two-argument Invoke(object?, object?, object?) overload throws TargetParameterCountException on both runtimes.
This came up in #135566, whose "Not changed" section lists it.
Reproduction Steps
using System;
using System.Reflection;
MethodInfo openType = typeof(C<>).GetMethod(nameof(C<int>.OneArg))!;
MethodInfo definition = typeof(C).GetMethod(nameof(C.GenericOneArg))!;
foreach (MethodInfo method in new[] { openType, definition })
{
MethodInvoker invoker = MethodInvoker.Create(method);
string name = $"{method.DeclaringType!.Name}.{method.Name}";
Run($"{name}, Span with 2 arguments", () => invoker.Invoke(null, new Span<object?>(new object?[] { 1, 2 })));
Run($"{name}, Span with 0 arguments", () => invoker.Invoke(null, new Span<object?>(new object?[0])));
Run($"{name}, 2 fixed arguments", () => invoker.Invoke(null, 1, 2));
}
static void Run(string label, Action action)
{
try
{
action();
Console.WriteLine($"{label}: no exception");
}
catch (Exception e)
{
Console.WriteLine($"{label}: {e.GetType().Name}");
}
}
static class C
{
public static T GenericOneArg<T>(T value) => value;
}
static class C<T>
{
public static T OneArg(T value) => value;
}Expected behavior
The same on both runtimes. Proposed: CoreCLR's:
C`1.OneArg, Span with 2 arguments: TargetParameterCountException
C`1.OneArg, Span with 0 arguments: TargetParameterCountException
C`1.OneArg, 2 fixed arguments: TargetParameterCountException
C.GenericOneArg, Span with 2 arguments: TargetParameterCountException
C.GenericOneArg, Span with 0 arguments: TargetParameterCountException
C.GenericOneArg, 2 fixed arguments: TargetParameterCountException
Other option considered: InvalidOperationException from the span overload on both runtimes: the two-argument overload already reports the wrong count with TargetParameterCountException on both.
Actual behavior
CoreCLR prints the output above. NativeAOT:
C`1.OneArg, Span with 2 arguments: InvalidOperationException
C`1.OneArg, Span with 0 arguments: InvalidOperationException
C`1.OneArg, 2 fixed arguments: TargetParameterCountException
C.GenericOneArg, Span with 2 arguments: InvalidOperationException
C.GenericOneArg, Span with 0 arguments: InvalidOperationException
C.GenericOneArg, 2 fixed arguments: TargetParameterCountException
Regression?
No. On .NET 9.0.21 the repro prints the same outputs as above. On 8.0.32 the open generic type gives the same outputs; for the generic method definition, NativeAOT already throws NotSupportedException from MethodInvoker.Create.
Known Workarounds
None needed: the call fails on both runtimes; only the exception type differs.
Configuration
.NET 9.0.21 and 10.0.13 (SDK 10.0.402) and 11.0.0-rc.1.26420.103 (SDK 11.0.100-rc.1.26420.103), Windows 11 x64; also 8.0.32 (SDK 10.0.402); NativeAOT published with dotnet publish -c Release -r win-x64 -p:PublishAot=true.
Other information
CoreCLR's span overload checks the count first:
public object? Invoke(object? obj, Span<object?> arguments)
{
int argLen = arguments.Length;
if (argLen != _argCount)
{
MethodBaseInvoker.ThrowTargetParameterCountException();
}NativeAOT's fixed-arity overloads check it too, but its span overload passes the arguments to the method's invoker, which for an open generic method is OpenMethodInvoker and throws InvalidOperationException without looking at them:
public object? Invoke(object? obj, Span<object?> arguments)
{
object? result = _methodBaseInvoker.Invoke(obj, arguments);
DebugAnnotations.PreviousCallContainsDebuggerStepInCode();
return result;
}I'm working on a fix and will open a PR for it. Could this be assigned to me?
Note
AI-generated, written at my direction and reviewed by me before posting. The repro above ran as dotnet exec (CoreCLR) and as a NativeAOT publish, with the SDKs and command under Configuration, on each release listed there.
Metadata
Metadata
Assignees
Labels
Type
Projects
- StatusShow more project fieldsNo status
Activity
dotnet-policy-service commentedon Oct 19, 2026
Tagging subscribers to this area: @agocke, @dotnet/ilc-contrib
See info in area-owners.md if you want to be subscribed.