dotnet/efcore · error · InvalidOperationException
An error occurred while reading a database value. The…
Error message
An error occurred while reading a database value. The expected type was '{expectedType}' but the actual value was 'null'. What it means
Thrown by ThrowReadValueException when the underlying data reader returned a null/DBNull for a value slot whose target CLR type is a non-nullable value type, and the shaper has no IProperty context (the else branch). EF wraps the NullReferenceException or DBNull-equivalent into an InvalidOperationException with a clear expected-type-vs-null message. It indicates the database row contained NULL where the materialization contract expected a value.
Solutions
- Make the projected CLR member nullable (int? / DateTime?) so DBNull maps cleanly.
- If reading an entity, mark the property as nullable in the model (IsRequired(false)) or add a NOT NULL default constraint.
- Update the database schema to disallow NULL and backfill existing NULL rows.
- For DTO projections, coerce in the selector: b.SomeIntColumn ?? 0.
Example fix
// before
var dtos = await db.Blogs
.Select(b => new BlogDto { Rank = b.Rank }) // Rank is int, column nullable
.ToListAsync();
// after
public class BlogDto { public int? Rank { get; set; } } Defensive patterns
Strategy: validation
Validate before calling
// before materializing, ensure projected members are nullable when the column is nullable
var rows = await db.Blogs
.Select(b => new BlogDto { Rank = (int?)b.Rank })
.ToListAsync(); Type guard
// narrow value-type results defensively static T? SafeRead<T>(object? v) where T : struct => v is DBNull or null ? null : (T)v;
Try / catch
try { var v = await query.FirstAsync(); }
catch (InvalidOperationException ex) when (ex.Message.Contains("actual value was 'null'"))
{
logger.LogWarning(ex, "Null in non-nullable projection; check schema/DTO");
throw;
} Prevention
- Make DTO members nullable when the source column permits NULL.
- Add NOT NULL default constraints before relying on non-nullable reads.
- For LEFT JOIN scenarios, project from the nullable side as nullable.
When it happens
Trigger: A DbDataReader slot yielded DBNull (or a NullReferenceException) during materialization of a projected value with no associated IProperty — typically inside a non-entity projection (e.g. a Select(b => new Dto { Count = b.SomeInt }) where the underlying column is null). The else branch fires because property is null.
Common situations: Database column is nullable but the projection CLR type is non-nullable int/DateTime/Guid; a LEFT JOIN produced NULL for the right side; default constraints were dropped so newly inserted rows have NULL where EF expects a value; views with outer joins materialized into value-type DTOs.
Related errors
- An error occurred while reading a database value. See the…
- An error occurred while reading a database value. The…
- An error occurred while reading a database value. The…
- An error occurred while reading a database value. The…
- An error occurred while reading a database value. See the…
AI-assisted analysis of dotnet/efcore@3a2006ef56 (2026-08-11).
Data as JSON: /api/errors/571f43ac7fb25223.
Report an issue: GitHub.
Appendix: source
Thrown at src/EFCore.Relational/Extensions/RelationalPropertyExtensions.cs:2048
message
= exception is NullReferenceException
|| Equals(value, DBNull.Value)
? RelationalStrings.ErrorMaterializingPropertyNullReference(entityType, propertyName, expectedType)
: exception is InvalidCastException
? CoreStrings.ErrorMaterializingPropertyInvalidCast(entityType, propertyName, expectedType, actualType)
: RelationalStrings.ErrorMaterializingProperty(entityType, propertyName);
}
else
{
message
= exception is NullReferenceException
? RelationalStrings.ErrorMaterializingValueNullReference(expectedType)
: exception is InvalidCastException
? RelationalStrings.ErrorMaterializingValueInvalidCast(expectedType, actualType)
: RelationalStrings.ErrorMaterializingValue;
}
throw new InvalidOperationException(message, exception);
}
/// <summary>
/// Gets the value of JSON property name used for the given property of an entity mapped to a JSON column.
/// </summary>
/// <remarks>
/// Unless configured explicitly, entity property name is used.
/// </remarks>
/// <param name="property">The property.</param>
/// <returns>
/// The value for the JSON property used to store the value of this entity property.
/// By default <see langword="null" /> is returned for key properties and for properties that
/// are not mapped to JSON.
/// </returns>
public static string? GetJsonPropertyName(this IReadOnlyProperty property)
=> (string?)property.FindAnnotation(RelationalAnnotationNames.JsonPropertyName)?.Value
?? (property.IsKey() || !property.DeclaringType.IsMappedToJson()
? nullView on GitHub (pinned to 3a2006ef56)