dotnet/efcore · error · InvalidOperationException

An error occurred while reading a database value. See the in

Error message

An error occurred while reading a database value. See the inner exception for more information.

What it means

Thrown by ThrowReadValueException in RelationalPropertyExtensions.cs:2048 while EF Core reads a column value out of a DbDataReader and materializes it into an entity/primitive. It wraps the real database/contractor exception (cast failure, null into non-nullable, DBNull, converter error) as its InnerException and re-throws as InvalidOperationException with a contextual message. The library does this so a raw ADO.NET failure is reported with the entity type and property name rather than an opaque cast.

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()
                ? null

View on GitHub (pinned to dbf9771522)

Solutions

  1. Inspect the InnerException (and its message) - it names the exact cast/conversion failure; the EF message only adds entity/property context.
  2. Compare the failing column's database type against the mapped CLR property (GetColumnType(), IsNullable) and reconcile the model or the schema with a migration.
  3. If a value converter is involved, verify ConverterClrType/ProviderClrType align with both the CLR property and the DB column type.
  4. Make the CLR property nullable (int?/DateTime?) if the column legitimately contains NULL, or add a database default/NOT NULL constraint with backfill.
  5. For transient/bad rows, project through a Select that normalizes the value before materialization.

Example fix

// before
public int StockCount { get; set; } // column is NULLABLE in DB -> NullReferenceException on read

// after (option A: make nullable)
public int? StockCount { get; set; }

// after (option B: ensure column NOT NULL with default)
// modelBuilder.Entity<Product>().Property(p => p.StockCount).HasDefaultValue(0);
Defensive patterns

Strategy: try-catch

Validate before calling

// Cannot fully validate pre-query; mitigate by checking nullability up front.
foreach (var prop in context.Model.GetEntityTypes().SelectMany(e => e.GetProperties()))
{
    if (!prop.IsNullable && prop.GetColumnType() is { } col
        && /* your schema metadata says column is nullable */ false)
    {
        // flag risk: non-nullable CLR property over a nullable column
    }
}

Try / catch

try
{
    var result = await query.ToListAsync();
}
catch (InvalidOperationException ex)
    when (ex.InnerException != null
         && (ex.InnerException is InvalidCastException
             || ex.InnerException is NullReferenceException
             || ex.InnerException is FormatException))
{
    // ex.Message names the entity/property; ex.InnerException is the real cause.
    logger.LogError(ex.InnerException, "Materialization failed reading {Message}", ex.Message);
    throw new MyDomainReadException("Bad data in result set; see inner.", ex.InnerException);
}

Prevention

When it happens

Trigger: Executing a query whose materializer calls the compiled value reader and the underlying DbDataReader.GetX()/value converter throws. Concrete triggers: a NULL lands on a non-nullable value-type property; a column value cannot be cast to the configured CLR type (e.g. string column into int); a value converter throws in ConvertFromProvider; the reader returns a type incompatible with the providerClrType.

Common situations: Database schema drifted from the model (column type changed, new NOT NULL without default), a value converter whose provider type mismatches the column, nullable DB column mapped to a non-nullable CLR property, regional/encoding issues producing unparseable values, importing legacy data with empty strings/DBNull where a numeric is expected.

Related errors


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