DapperLib/Dapper · error · ArgumentNullException
type
Error message
type
What it means
GridReader.ReadAsync(Type type, bool buffered) is the non-generic async overload that materializes the next result grid into instances of a runtime Type. It throws ArgumentNullException(nameof(type)) at SqlMapper.GridReader.Async.cs:54 when type is null. The generic ReadAsync<T> overloads cannot hit this because typeof(T) is always non-null.
Source
Thrown at Dapper/SqlMapper.GridReader.Async.cs:54
/// </summary>
/// <remarks>Note: the row can be accessed via "dynamic", or by casting to an IDictionary<string,object></remarks>
public Task<dynamic> ReadSingleAsync() => ReadRowAsyncImpl<dynamic>(typeof(DapperRow), Row.Single);
/// <summary>
/// Read an individual row of the next grid of results, returned as a dynamic object
/// </summary>
/// <remarks>Note: the row can be accessed via "dynamic", or by casting to an IDictionary<string,object></remarks>
public Task<dynamic?> ReadSingleOrDefaultAsync() => ReadRowAsyncImpl<dynamic?>(typeof(DapperRow), Row.SingleOrDefault);
/// <summary>
/// Read the next grid of results
/// </summary>
/// <param name="type">The type to read.</param>
/// <param name="buffered">Whether to buffer the results.</param>
/// <exception cref="ArgumentNullException"><paramref name="type"/> is <c>null</c>.</exception>
public Task<IEnumerable<object>> ReadAsync(Type type, bool buffered = true)
{
if (type is null) throw new ArgumentNullException(nameof(type));
return ReadAsyncImpl<object>(type, buffered);
}
/// <summary>
/// Read an individual row of the next grid of results
/// </summary>
/// <param name="type">The type to read.</param>
/// <exception cref="ArgumentNullException"><paramref name="type"/> is <c>null</c>.</exception>
public Task<object> ReadFirstAsync(Type type)
{
if (type is null) throw new ArgumentNullException(nameof(type));
return ReadRowAsyncImpl<object>(type, Row.First);
}
/// <summary>
/// Read an individual row of the next grid of results.
/// </summary>
/// <param name="type">The type to read.</param>
View on GitHub (pinned to 72a54c475f)
Solutions
- Null-check type before the call: if (type is null) throw ...; or fall back to a default type.
- Prefer the generic overload ReadAsync<T>() which makes a null type unrepresentable.
- Validate the Type source (Type.GetType / Assembly.GetType) for null immediately after resolution and log the failing type name.
Example fix
// before
Type t = Type.GetType(typeName); // null if not found
var rows = await grid.ReadAsync(t);
// after
Type t = Type.GetType(typeName) ?? throw new InvalidOperationException($"Unknown type: {typeName}");
var rows = await grid.ReadAsync(t); Defensive patterns
Strategy: validation
Validate before calling
if (type is null) throw new InvalidOperationException("type must be resolved before reading a grid");
var rows = await grid.ReadAsync(type); Type guard
static Type? ResolveType(string name) => Type.GetType(name);
// before use:
Type t = ResolveType(name) ?? throw new InvalidOperationException($"Unresolved type {name}"); Prevention
- Prefer generic ReadAsync<T>() over the Type-based overload.
- Resolve Types once at startup and reject nulls with a named error.
- Use Type.GetType with the fully qualified assembly-qualified name.
When it happens
Trigger: Call grid.ReadAsync((Type)null) on a GridReader from QueryMultipleAsync. Typical when the Type comes from a variable, reflection, or a config lookup that resolved to null.
Common situations: Mapping result sets by type loaded via Type.GetType(name) where the name was wrong and returned null; deserialization dispatch tables with a missing entry; runtime polymorphic readers.
Related errors
- type
- This operation requires an identity or a connected command
- The reader has been disposed; this can happen after all data
- type
- Async operations require use of a DbConnection or an already
AI-assisted analysis of DapperLib/Dapper@72a54c475f (2026-08-13).
Data as JSON: /api/errors/779ed5a3874c9a4a.
Report an issue: GitHub.