dotnet/BenchmarkDotNet · error · InvalidOperationException

Benchmark {benchmark.Name} has invalid number of arguments p

Error message

Benchmark {benchmark.Name} has invalid number of arguments provided by [ArgumentsSource({valuesInfo.source.Name})]! {array.Length} instead of {parameterDefinitions.Length}.

What it means

Thrown by SmartParamBuilder.CreateForArguments when a benchmark method with multiple parameters is fed an object[] from [ArgumentsSource] whose element count does not match the benchmark's parameter count. The check `parameterDefinitions.Length != array.Length` fires inside the branch where the benchmark has more than one parameter and the yielded array does not align.

Source

Thrown at src/BenchmarkDotNet/Parameters/SmartParamBuilder.cs:45

        internal static ParameterInstances CreateForArguments(MethodInfo benchmark, ParameterDefinition[] parameterDefinitions, (MemberInfo source, object[] values) valuesInfo, int sourceIndex, SummaryStyle summaryStyle)
        {
            var unwrappedValue = valuesInfo.values[sourceIndex];

            if (unwrappedValue is object[] array)
            {
                Type? firstParamType = benchmark.GetParameters().FirstOrDefault()?.ParameterType;
                // the user provided object[] for a benchmark accepting a single argument
                if (parameterDefinitions.Length == 1 && array.Length == 1
                    && (array[0]?.GetType() == firstParamType || (firstParamType != null && firstParamType.IsStackOnlyWithImplicitCast(array[0])))) // the benchmark that accepts an object[] as argument
                {
                    return new ParameterInstances(
                        [Create(parameterDefinitions, array[0], valuesInfo.source, sourceIndex, argumentIndex: 0, summaryStyle)]);
                }

                if (parameterDefinitions.Length > 1)
                {
                    if (parameterDefinitions.Length != array.Length)
                        throw new InvalidOperationException($"Benchmark {benchmark.Name} has invalid number of arguments provided by [ArgumentsSource({valuesInfo.source.Name})]! {array.Length} instead of {parameterDefinitions.Length}.");

                    return new ParameterInstances(
                        array.Select((value, argumentIndex) => Create(parameterDefinitions, value, valuesInfo.source, sourceIndex, argumentIndex, summaryStyle)).ToArray());
                }
            }

            if (parameterDefinitions.Length == 1)
            {
                return new ParameterInstances([Create(parameterDefinitions, unwrappedValue, valuesInfo.source, sourceIndex, argumentIndex: 0, summaryStyle)]);
            }

            throw new NotSupportedException($"Benchmark {benchmark.Name} has invalid type of arguments provided by [ArgumentsSource({valuesInfo.source.Name})]. It should be IEnumerable<object[]> or IEnumerable<object>.");
        }

        private static ParameterInstance Create(ParameterDefinition[] parameterDefinitions, object value, MemberInfo source, int sourceIndex, int argumentIndex, SummaryStyle summaryStyle)
        {
            if (SourceCodeHelper.IsCompilationTimeConstant(value))
                return new ParameterInstance(parameterDefinitions[argumentIndex], value, summaryStyle);

View on GitHub (pinned to b515068b61)

Solutions

  1. Count the benchmark method parameters and ensure every object[] yielded by the source has exactly that length.
  2. Use a helper that constructs each row from named fields to avoid manual array sizing.
  3. If a single object[] argument is intended (benchmark takes object[] as one parameter), ensure only one parameter is declared and the source yields single-element arrays or scalar objects.

Example fix

// before
public IEnumerable<object[]> Data() => new[]
{
    new object[] { 1, 2 }, // method has 3 params!
};
[Benchmark]
[ArgumentsSource(nameof(Data))]
public void Run(int a, int b, int c) { }

// after
public IEnumerable<object[]> Data() => new[]
{
    new object[] { 1, 2, 3 },
};
Defensive patterns

Strategy: validation

Validate before calling

// Verify each ArgumentsSource row matches the benchmark parameter count
int paramCount = typeof(MyBench).GetMethod(nameof(MyBench.Run))!.GetParameters().Length;
foreach (var row in Data())
    if (row.Length != paramCount)
        throw new InvalidOperationException($"Row has {row.Length} elements, expected {paramCount}");

Prevention

When it happens

Trigger: A benchmark method declared as void Run(int a, int b, int c) with [ArgumentsSource(nameof(Data))] where Data yields object[] arrays of length 2 or 4 instead of 3. Each yielded array must exactly match the parameter count when the method has >1 parameter.

Common situations: Adding or removing a parameter from a benchmark method signature but forgetting to update the ArgumentsSource data provider. Returning jagged arrays of inconsistent lengths. Misunderstanding that for multi-parameter benchmarks each yielded item must be an array matching the full signature.

Related errors


AI-assisted analysis of dotnet/BenchmarkDotNet@b515068b61 (2026-08-13). Data as JSON: /api/errors/52c096ffba8a59df. Report an issue: GitHub.