dotnet/BenchmarkDotNet · error · ArgumentException
The optionalLocalThis should be null for static calls
Error message
The optionalLocalThis should be null for static calls
What it means
EmitCallCore (internal) throws ArgumentException when emitting a static call (methodToCall.IsStatic) but optionalLocalThis is non-null. A static call has no 'this', so providing a local for 'this' is contradictory and would produce invalid IL.
Source
Thrown at src/BenchmarkDotNet/Helpers/Reflection.Emit/IlGeneratorCallExtensions.cs:81
MethodInfo methodToCall,
IEnumerable<LocalBuilder> argLocals,
bool forceDirectCall = false)
{
if (methodToCall.DeclaringType == null)
throw new ArgumentException($"The {nameof(methodToCall)} should have non-null {nameof(methodToCall.DeclaringType)}.");
/*
IL_0000: call class [mscorlib]System.Threading.Tasks.Task [mscorlib]System.Threading.Tasks.Task::get_CompletedTask()
-or-
IL_0007: callvirt instance valuetype [mscorlib]System.Runtime.CompilerServices.TaskAwaiter`1<!0> class [mscorlib]System.Threading.Tasks.Task`1<int32>::GetAwaiter()
--or-
IL_000d: ldloca.s 0
IL_000f: call instance !0 valuetype [mscorlib]System.Runtime.CompilerServices.TaskAwaiter`1<int32>::GetResult()
*/
if (methodToCall.IsStatic)
{
if (optionalLocalThis != null)
throw new ArgumentException($"The {nameof(optionalLocalThis)} should be null for static calls", nameof(optionalLocalThis));
ilBuilder.EmitLdLocals(argLocals);
ilBuilder.Emit(OpCodes.Call, methodToCall);
}
else if (methodToCall.DeclaringType.IsValueType)
{
ArgumentNullException.ThrowIfNull(optionalLocalThis);
ilBuilder.EmitLdloca(optionalLocalThis);
ilBuilder.EmitLdLocals(argLocals);
ilBuilder.Emit(OpCodes.Call, methodToCall);
}
else
{
if (optionalLocalThis != null)
ilBuilder.EmitLdloc(optionalLocalThis);
ilBuilder.EmitLdLocals(argLocals);View on GitHub (pinned to b515068b61)
Solutions
- Retry with a simpler benchmark method (plain instance method) to avoid the misrouted emit path.
- Upgrade BenchmarkDotNet; report a reproducible issue if it continues.
Defensive patterns
Strategy: try-catch
Try / catch
try { runner.Run(); }
catch (ArgumentException ex) when (ex.Message.Contains("should be null for static calls")) { /* simplify benchmark, report issue */ } Prevention
- Use conventional benchmark method shapes to avoid emit misrouting.
- Keep BenchmarkDotNet current.
- File reproducible codegen issues.
When it happens
Trigger: The emitter routes to the static-call branch while a LocalBuilder for 'this' was also supplied, i.e. an internal caller passed conflicting arguments.
Common situations: Library codegen bug misclassifying a call as static while still supplying a this-local; not user-facing configuration.
Related errors
- Method {methodToCall} should be static method.
- The methodToCall should have non-null DeclaringType.
- Method {methodToCall} should be instance method.
- Can not emit base call for {constructorBuilder}
- The constructorBuilder should have non-null DeclaringType.
AI-assisted analysis of dotnet/BenchmarkDotNet@b515068b61 (2026-08-13).
Data as JSON: /api/errors/855573c4ebe92354.
Report an issue: GitHub.