dotnet/BenchmarkDotNet · error · InvalidOperationException

Failed to determine type of array elements

Error message

Failed to determine type of array elements

What it means

Inside ArrayParam.FromObject, after the IsArray check passes, type.GetElementType() is expected to yield the element type. For genuine CLR arrays this is essentially always non-null, so this throw is a defensive guard against exotic or edge-case array-like types where GetElementType returns null (e.g. certain Array-derived types or by-ref-like constructs produced via reflection).

Source

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

        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. Use a concrete, standard array type (int[], string[], etc.) instead of an Array subclass or reflected construct.
  2. If you control the value, materialize it as a normal T[] before passing it in.
  3. Report it as a BDN issue if a plain array still triggers it, including the exact runtime/Type involved.

Example fix

// before
var arg = Array.CreateInstance(typeof(int), lengths, lowerBounds); // non-zero-based Array subclass

// after
var arg = new int[] { 1, 2, 3 }; // standard zero-based array
Defensive patterns

Strategy: type-guard

Validate before calling

var t = array.GetType();
if (!t.IsArray || t.GetElementType() is null)
    throw new ArgumentException("A standard zero-based array is required.", nameof(array));
return ArrayParam.FromObject(array);

Type guard

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

Try / catch

try { return ArrayParam.FromObject(obj); }
catch (InvalidOperationException ex) when (ex.Message.Contains("Failed to determine type"))
{
    // copy into a concrete T[] and retry
}

Prevention

When it happens

Trigger: Passing a Type whose IsArray is true but whose GetElementType() returns null, which can occur with non-standard Array subclasses or some reflected/constructed array types; not reachable with ordinary T[] values.

Common situations: Custom IParam providers or reflection-based argument plumbing that construct unusual array types, or runtime/CLR edge cases on uncommon targets.

Related errors


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