dotnet/efcore · error · InvalidOperationException
The complex collection property '{entityType}.{property}' mu
Error message
The complex collection property '{entityType}.{property}' must be mapped to a JSON column. Use 'ToJson()' to configure this complex collection as mapped to a JSON column. What it means
ValidatePropertyMapping (RelationalModelValidator.cs:267-272) throws when a complex property is a collection (complexProperty.IsCollection) but its complex type is not mapped to JSON. Relational providers require complex collections to be stored as a JSON column (there is no table-per-row mapping for an arbitrary complex collection without an entity key), so the model is rejected unless ToJson() is configured.
Source
Thrown at src/EFCore.Relational/Infrastructure/RelationalModelValidator.cs:269
if (property is { IsPrimitiveCollection: true }
&& property.GetTypeMapping().ElementTypeMapping?.ElementTypeMapping != null)
{
throw new InvalidOperationException(
RelationalStrings.NestedCollectionsNotSupported(
property.ClrType.ShortDisplayName(), property.DeclaringType.DisplayName(), property.Name));
}
}
/// <inheritdoc />
protected override void ValidatePropertyMapping(
IComplexProperty complexProperty,
IDiagnosticsLogger<DbLoggerCategory.Model.Validation> logger)
{
base.ValidatePropertyMapping(complexProperty, logger);
if (complexProperty.IsCollection && !complexProperty.ComplexType.IsMappedToJson())
{
throw new InvalidOperationException(
RelationalStrings.ComplexCollectionNotMappedToJson(
complexProperty.DeclaringType.DisplayName(), complexProperty.Name));
}
if (!complexProperty.ComplexType.IsMappedToJson()
&& complexProperty.IsNullable
&& complexProperty.ComplexType.GetProperties().All(m => m.IsNullable))
{
throw new InvalidOperationException(
RelationalStrings.ComplexPropertyOptionalTableSharing(complexProperty.ComplexType.DisplayName(), complexProperty.Name));
}
if (complexProperty.GetJsonPropertyName() != null)
{
if (complexProperty.ComplexType.FindAnnotation(RelationalAnnotationNames.ContainerColumnName)?.Value is string columnName)
{
throw new InvalidOperationException(
RelationalStrings.ComplexPropertyBothJsonColumnAndJsonPropertyName(View on GitHub (pinned to dbf9771522)
Solutions
- Add .ToJson("ColumnName") to the complex collection configuration so it persists as a JSON column.
- If you actually want rows in a separate table, use an owned entity collection (OwnsMany with an owned ENTITY type that has identity) instead of a complex type.
- Verify the complex type is declared via ComplexType/OwnsMany complex and that ToJson is applied to the collection property.
Example fix
// before
modelBuilder.Entity<Order>().OwnsMany(o => o.Tags, t =>
{
t.ComplexProperty(p => p.Style); // Tags is a complex collection not mapped to JSON -> throws
});
// after
modelBuilder.Entity<Order>().OwnsMany(o => o.Tags, t =>
{
t.ToJson("TagsJson");
t.ComplexProperty(p => p.Style);
}); Defensive patterns
Strategy: validation
Validate before calling
foreach (var et in context.Model.GetEntityTypes())
{
foreach (var cp in et.GetComplexProperties().Where(cp => cp.IsCollection))
{
if (!cp.ComplexType.IsMappedToJson())
{
// will throw - add .ToJson("col") to this complex collection.
}
}
} Prevention
- Always pair OwnsMany of a complex collection with ToJson().
- Use owned ENTITY collections (with identity) when you want a child table instead of JSON.
- Add a build-time check that every complex collection is JSON-mapped.
When it happens
Trigger: Declaring OwnsMany(...) / a complex collection property without calling ToJson() on it. Triggered during model validation when the context first builds.
Common situations: Adding OwnsMany of a value-object-like complex type assuming it maps to a child table (it does not - owned entity collections map to tables, complex collections must be JSON); forgetting the ToJson() call after introducing a complex collection.
Related errors
- The partition key property '{property1}' on '{entityType1}'
- Both properties '{property1}' and '{property2}' on entity ty
- The property '{property}' on type '{type}' is mapped to a JS
- The key {keyProperties} on the entity type '{entityType}' ca
- The property '{propertyType} {type}.{property}' is a primiti
AI-assisted analysis of dotnet/efcore@dbf9771522 (2026-08-06).
Data as JSON: /api/errors/c8ab7b36f918d98e.
Report an issue: GitHub.