dotnet/BenchmarkDotNet · error · ArgumentException
Extend a MethodCallExpression, but got a
Error message
Extend a MethodCallExpression, but got a
What it means
GetReportFor<T> requires the expression body to be a MethodCallExpression so it can read the invoked MethodInfo. It throws ArgumentException with the actual body type name when the lambda is not a direct method invocation (e.g. a property access, field access, arithmetic, or conversion).
Source
Thrown at src/BenchmarkDotNet/Extensions/ReportExtensions.cs:15
using BenchmarkDotNet.Mathematics;
using BenchmarkDotNet.Reports;
using System.Linq.Expressions;
namespace BenchmarkDotNet.Extensions
{
public static class ReportExtensions
{
public static BenchmarkReport GetReportFor<T>(this Summary summary, Expression<Action<T>> actionExp)
{
if (actionExp.Body == null)
throw new ArgumentException("Extend a an Expression with a valid Body", nameof(actionExp));
if (!(actionExp.Body is MethodCallExpression methodExp))
throw new ArgumentException("Extend a MethodCallExpression, but got a " + actionExp.Body.GetType().Name, nameof(actionExp));
return summary.Reports.First(r => r.BenchmarkCase.Descriptor.WorkloadMethod == methodExp.Method);
}
public static IList<Measurement> GetRunsFor<T>(this Summary summary, Expression<Action<T>> actionExp)
{
return summary.GetReportFor(actionExp).GetResultRuns().ToList();
}
public static Statistics GetStatistics(this IReadOnlyCollection<Measurement> runs)
{
if (runs.IsEmpty())
throw new InvalidOperationException("List of measurements contains no elements");
return new Statistics(runs.Select(r => r.GetAverageTime().Nanoseconds));
}
public static Statistics GetStatistics(this IEnumerable<Measurement> runs) =>
GetStatistics(runs.ToList());View on GitHub (pinned to b515068b61)
Solutions
- Pass a lambda that directly invokes the benchmark method: summary.GetReportFor(b => b.MyBenchmark()).
- Ensure the lambda contains exactly one method call and no wrapping conversions, ternaries, or member accesses.
- If you only have a MethodInfo, locate the report manually via summary.Reports.First(r => r.BenchmarkCase.Descriptor.WorkloadMethod == method).
Example fix
// before var report = summary.GetReportFor(b => b.SomeProperty); // after var report = summary.GetReportFor(b => b.Run());
Defensive patterns
Strategy: type-guard
Validate before calling
Expression<Action<T>> expr = b => b.Run();
if (expr.Body is not MethodCallExpression mce)
throw new InvalidOperationException("expression body must be a method call");
var report = summary.GetReportFor(expr); Type guard
static bool IsMethodCallExpression<T>(Expression<Action<T>> expr) => expr?.Body is MethodCallExpression;
Prevention
- Pass a single method-invocation lambda to GetReportFor.
- Avoid property/field/arithmetic lambdas with this API.
- Use a type guard (is MethodCallExpression) when expressions come from dynamic sources.
When it happens
Trigger: Calling summary.GetReportFor(b => b.SomeProperty), summary.GetReportFor(b => b.Field), summary.GetReportFor(b => 1 + 1), or any lambda whose body is not a method call.
Common situations: Misunderstanding the API as a generic expression evaluator; passing a property getter or a composed expression instead of a single method-call lambda; refactoring a benchmark from a method to a property and forgetting to update the call.
Related errors
- Extend a an Expression with a valid Body
- List of measurements contains no elements
- 'source' cannot be null or whitespace.
- Missing extension on source '{source}', must have the extens
- Unsupported extension on source '{source}', must have the ex
AI-assisted analysis of dotnet/BenchmarkDotNet@b515068b61 (2026-08-13).
Data as JSON: /api/errors/3aa6afadadbf7741.
Report an issue: GitHub.