dotnet/efcore · error · InvalidOperationException
An error occurred while reading a database value. The expect
Error message
An error occurred while reading a database value. The expected type was '{expectedType}' but the actual value was of type '{actualType}'. What it means
Thrown by ThrowReadValueException when the data reader returned a value whose runtime type cannot be cast to the expected CLR type, surfaced as an InvalidCastException wrapper. Fires in the property-less else branch — i.e. a projected value, not an entity property. The message reports both the expected type (the generic TValue) and the actual runtime type returned by the driver.
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)
Solutions
- Align the projected CLR type with the column's mapped type — query property.GetColumnType() or sp_help to confirm.
- Add a HasConversion on the source property, or coerce in the projection (e.g. b.Id.ToString()).
- For FromSqlRaw, verify the SELECT column order and types match the DTO field order and types.
- Upgrade the provider package in lockstep with EF Core so type mappings stay consistent.
Example fix
// before
var ids = await db.Database.SqlQueryRaw<Guid>("SELECT token FROM tokens").ToListAsync();
// after — token column is varchar
var ids = await db.Database.SqlQueryRaw<string>("SELECT token FROM tokens").ToListAsync(); Defensive patterns
Strategy: validation
Validate before calling
// confirm the column type matches TValue before projecting
var columnType = property.GetColumnType();
if (!typeof(TValue).IsAssignableFrom(map.GetClrType(columnType)))
throw new InvalidOperationException($"Type mismatch: {columnType} -> {typeof(TValue)}"); Type guard
static bool CanMapTo(Type clrType, string storeType, IRelationalTypeMappingSource src)
=> src.FindMapping(clrType, storeType) is not null; Try / catch
try { var v = await query.ToListAsync(); }
catch (InvalidOperationException ex) when (ex.Message.Contains("actual value was of type"))
{
logger.LogError(ex, "Type mismatch during materialization; inner: {Inner}", ex.InnerException?.Message);
throw;
} Prevention
- Keep provider and EF Core packages version-aligned to preserve type mappings.
- For FromSqlRaw, validate SELECT column order and types against the DTO.
- Add HasConversion when the column type and CLR type intentionally differ.
When it happens
Trigger: Materializing a projected value where the database column type differs from the CLR type and the ADO.NET driver cannot convert (e.g. SQL column is VARCHAR but TValue is Guid; or a JSON column returns string while TValue is JObject). Distinct from the property-keyed variant because no IProperty is bound at the throw site.
Common situations: Raw SQL projections with FromSqlRaw into a non-entity type whose column order/types drifted from the DTO; manual DbDataReader usage bridged into EF; provider version upgrades that changed type mapping defaults (e.g. byte[] vs string); misconfigured value converters on projections.
Related errors
- An error occurred while reading a database value. The expect
- The type '{givenType}' cannot be mapped as a dictionary beca
- The type of the etag property '{property}' on '{entityType}'
- The type '{clrType}' is being used as a vector, but the vect
- The 'VectorDistance' function can only be used with a proper
AI-assisted analysis of dotnet/efcore@3a2006ef56 (2026-08-11).
Data as JSON: /api/errors/9ee1dd5e70520af1.
Report an issue: GitHub.