dotnet/BenchmarkDotNet · error · InvalidOperationException

The argument must be an array

Error message

The argument must be an array

What it means

ArrayParam.FromObject is the reflection entry point used when a benchmark argument or [Params] value is supplied as a boxed object that BDN must render into source code. It requires the object to be an actual array (type.IsArray true). If the object is a List, IEnumerable, a scalar, or any other reference/collection type, IsArray is false and it throws InvalidOperationException.

Source

Thrown at src/BenchmarkDotNet/Code/ArrayParam.cs:72

        /// <summary>
        /// for types where calling .ToString() will be enough to re-create them in auto-generated source code file (integers, strings and other primitives)
        /// </summary>
        public static ArrayParam<T> ForPrimitives(T[] array) => new ArrayParam<T>(array);

        /// <summary>
        /// for types where calling .ToString() will be NOT enough to re-create them in auto-generated source code file
        /// </summary>
        /// <param name="array">the array</param>
        /// <param name="toSourceCode">method which transforms an item of type T to it's C# representation
        /// example: point => $"new Point2d({point.X}, {point.Y})"
        /// </param>
        [PublicAPI] public static ArrayParam<T> ForComplexTypes(T[] array, Func<T, string> toSourceCode) => new ArrayParam<T>(array, toSourceCode);

        internal static IParam? FromObject(object array)
        {
            var type = array.GetType();
            if (!type.IsArray)
                throw new InvalidOperationException("The argument must be an array");
            var elementType = type.GetElementType();
            if (elementType == null)
                throw new InvalidOperationException("Failed to determine type of array elements");
            if (!SourceCodeHelper.IsCompilationTimeConstant(elementType))
                throw new InvalidOperationException("The argument must be an array of primitives");

            var arrayParamType = typeof(ArrayParam<>).MakeGenericType(elementType);

            var methodInfo = arrayParamType.GetMethod(nameof(ForPrimitives), BindingFlags.Public | BindingFlags.Static)
                ?? throw new InvalidOperationException($"{nameof(ForPrimitives)} not found");
            return (IParam?)methodInfo.Invoke(null, [array]);
        }
    }
}

View on GitHub (pinned to b515068b61)

Solutions

  1. Convert the collection to an array before it reaches BDN: values.ToArray().
  2. For [ParamsSource], return an IReadOnlyList/array of the element type, not a List of arrays.
  3. Ensure [Arguments] array arguments are declared as actual T[] parameters.
  4. For complex element types, use ArrayParam<T>.ForComplexTypes(arr, toSourceCode) instead of FromObject.

Example fix

// before
public IEnumerable<object> Values() => new List<object> { 1, 2, 3 };
[ParamsSource(nameof(Values))] public int N;

// after
public IEnumerable<int> Values() => new[] { 1, 2, 3 };
[ParamsSource(nameof(Values))] public int N;
Defensive patterns

Strategy: type-guard

Validate before calling

if (array == null || !array.GetType().IsArray)
    throw new ArgumentException("An array argument is required.", nameof(array));
return ArrayParam.FromObject(array);

Type guard

static bool IsArrayParamCompatible(object? o) => o is not null && o.GetType().IsArray;

Try / catch

try { return ArrayParam.FromObject(obj); }
catch (InvalidOperationException ex) when (ex.Message.Contains("must be an array"))
{
    // materialize to an array and retry, or reject the param source
}

Prevention

When it happens

Trigger: Passing a non-array (List<T>, IEnumerable<T>, a single value, or a jagged/complex object) where BDN expects an array argument via [Arguments] / [ParamsSource] / global arguments that route through FromObject.

Common situations: Using [ParamsSource] that returns a List instead of an array, supplying a single object instead of an array, or a custom IParam implementation that calls FromObject on incompatible input.

Related errors


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