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

Materialization type mismatch: ThrowReadValueException reports 'expected type was X but the actual value was of type Y' when the underlying GetFieldValue throws InvalidCastException because the database value's runtime type cannot be coerced into the shaper's expected CLR type. The expected and actual type names are included.

Source

Thrown at src/EFCore.Relational/Query/Internal/BufferedDataReader.cs:1934

                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
                    || Equals(value, DBNull.Value)
                        ? RelationalStrings.ErrorMaterializingValueNullReference(expectedType)
                        : exception is InvalidCastException
                            ? RelationalStrings.ErrorMaterializingValueInvalidCast(expectedType, actualType)
                            : RelationalStrings.ErrorMaterializingValue;
            }

            throw new InvalidOperationException(message, exception);
        }
    }
}

View on GitHub (pinned to dbf9771522)

Solutions

  1. Add a HasConversion on the property to convert between the DB type and the CLR type (e.g. enum <-> string).
  2. Change the CLR property type to match what the provider returns (e.g. long instead of int).
  3. Fix the stored data / SQL so the column's type matches the model.
  4. For SQLite dynamic typing, ensure stored values are of the expected type or use conversions.

Example fix

// before - DB stores enum as string, property is enum (no conversion)
public OrderStatus Status { get; set; }

// after - explicit conversion
modelBuilder.Entity<Order>()
    .Property(o => o.Status)
    .HasConversion<string>();
Defensive patterns

Strategy: validation

Validate before calling

foreach (var et in dbContext.Model.GetEntityTypes())
foreach (var p in et.GetProperties())
    if (p.ClrType.IsEnum && p.GetValueConverter() == null && p.GetColumnType() is string s && s.Contains("char"))
        Console.WriteLine($"{et}.{p.Name}: enum likely stored as string but has no conversion; add .HasConversion<string>().");

Try / catch

try { return ctx.Set<T>().ToList(); }
catch (InvalidOperationException ex) when (ex.Message.Contains("expected type was") && ex.Message.Contains("actual value was of type"))
{ _logger.LogError(ex, "Type mismatch on materialization; add HasConversion or change CLR type."); throw; }

Prevention

When it happens

Trigger: A column returns a value of a type incompatible with the mapped property (e.g. DB returns string but property is int; provider returns long for an int property on some dialects); a value converter mismatch; enum stored as string but mapped as int without conversion.

Common situations: Enum stored as string in DB but property is the enum/int without HasConversion; JSON/JSONB returned as string but property is a typed object; provider returning a different numeric type (e.g. bigint for an int column); SQLite dynamic typing where a column holds an unexpected type.

Related errors


AI-assisted analysis of dotnet/efcore@dbf9771522 (2026-08-06). Data as JSON: /api/errors/5b0cf0582713b173. Report an issue: GitHub.