DapperLib/Dapper · error · ArgumentException

you must provide at least one type to deserialize

Error message

you must provide at least one type to deserialize

What it means

Thrown by MultiMapImpl when the `types` array passed to a multi-mapping query has zero elements. Dapper needs at least one concrete type so it can build a deserializer for the first result set; an empty array gives it nothing to map onto. This guards the non-generic `Query<TReturn>(cnn, sql, Type[] types, ...)` overload (SqlMapper.cs:1569), which is the only public entry point that lets the caller supply the type list directly.

Source

Thrown at Dapper/SqlMapper.cs:1654

                finally
                {
                    ownedCommand?.Parameters.Clear();
                    ownedCommand?.Dispose();
                    if (wasClosed) cnn!.Close();
                }
            }
        }

        private static CommandBehavior GetBehavior(bool close, CommandBehavior @default)
        {
            return (close ? (@default | CommandBehavior.CloseConnection) : @default) & Settings.AllowedCommandBehaviors;
        }

        private static IEnumerable<TReturn> MultiMapImpl<TReturn>(this IDbConnection? cnn, CommandDefinition command, Type[] types, Func<object[], TReturn> map, string splitOn, DbDataReader? reader, Identity? identity, bool finalize)
        {
            if (types.Length < 1)
            {
                throw new ArgumentException("you must provide at least one type to deserialize");
            }

            object? param = command.Parameters;
            identity ??= new IdentityWithTypes(command.CommandText, command.CommandTypeDirect, cnn!, types[0], param?.GetType(), types);
            CacheInfo cinfo = GetCacheInfo(identity, param, command.AddToCache);

            IDbCommand? ownedCommand = null;
            DbDataReader? ownedReader = null;

            bool wasClosed = cnn?.State == ConnectionState.Closed;
            try
            {
                if (reader is null)
                {
                    ownedCommand = command.SetupCommand(cnn!, cinfo.ParamReader);
                    if (wasClosed) cnn!.Open();
                    ownedReader = ExecuteReaderWithFlagsFallback(ownedCommand, wasClosed, CommandBehavior.SequentialAccess | CommandBehavior.SingleResult);
                    reader = ownedReader;

View on GitHub (pinned to 72a54c475f)

Solutions

  1. Pass at least one Type in the array, e.g. `new[] { typeof(Customer) }`.
  2. If you do not need multi-mapping, switch to the plain `Query<T>(sql)` overload instead of the `Type[]` overload.
  3. Guard the caller: if `types.Length == 0`, skip the query or throw a clearer domain-level exception.
  4. Prefer the strongly-typed generic `Query<TFirst,TSecond,TReturn>(...)` overload so the compiler enforces the type count.

Example fix

// before
var rows = cnn.Query<Result>(sql, new Type[0], objs => (Result)objs[0]);
// after
var rows = cnn.Query<Result>(sql, new[] { typeof(Result) }, objs => (Result)objs[0]);
Defensive patterns

Strategy: validation

Validate before calling

if (types is null || types.Length < 1) throw new ArgumentException("Multi-map requires at least one type.", nameof(types));
var rows = cnn.Query<TReturn>(sql, types, map, param);

Type guard

static bool HasMapTypes(Type[] types) => types is not null && types.Length > 0;

Prevention

When it happens

Trigger: Calling `connection.Query<TReturn>(sql, types: Array.Empty<Type>(), map: arr => ...)` or passing any zero-length `Type[]` as the third argument to that overload. The generic `Query<TFirst,TSecond,...>` overloads never hit this because they always construct a populated type array internally.

Common situations: Dynamically building the `types` array from reflection or user input and forgetting the case where the source list is empty; refactoring away the last mapped type; copy-pasting a multi-map call and deleting the type arguments.

Related errors


AI-assisted analysis of DapperLib/Dapper@72a54c475f (2026-08-13). Data as JSON: /api/errors/34b194caf48402fa. Report an issue: GitHub.