dotnet/efcore · error · InvalidOperationException
Complex property '{complexProperty}' is mapped to JSON but i
Error message
Complex property '{complexProperty}' is mapped to JSON but its containing type '{containingType}' is not. Map the root complex type to JSON. See https://github.com/dotnet/efcore/issues/36558. What it means
ValidatePropertyMapping (RelationalModelValidator.cs:301-311, tracking issue #36558) throws when a complex property is mapped to JSON but its declaring type is itself a complex type that is NOT mapped to JSON. A JSON column must be rooted at an entity (table); a complex type that flattens to columns cannot host a JSON sub-document. The whole JSON branch must be rooted in JSON, so EF rejects nested JSON inside a table-shared complex type.
Source
Thrown at src/EFCore.Relational/Infrastructure/RelationalModelValidator.cs:307
columnName,
complexProperty.GetJsonPropertyName()));
}
if (!complexProperty.DeclaringType.IsMappedToJson())
{
throw new InvalidOperationException(
RelationalStrings.ComplexPropertyJsonPropertyNameWithoutJsonMapping(
$"{complexProperty.DeclaringType.DisplayName()}.{complexProperty.Name}"));
}
}
if (complexProperty.ComplexType.IsMappedToJson())
{
if (!complexProperty.DeclaringType.IsMappedToJson()
&& complexProperty.DeclaringType is IComplexType)
{
// Issue #36558
throw new InvalidOperationException(
RelationalStrings.NestedComplexPropertyJsonWithTableSharing(
$"{complexProperty.DeclaringType.DisplayName()}.{complexProperty.Name}",
complexProperty.DeclaringType.DisplayName()));
}
ValidateJsonProperties(complexProperty.ComplexType);
}
}
/// <summary>
/// Validates the SQL query mapping for an entity type.
/// </summary>
/// <param name="entityType">The entity type to validate.</param>
/// <param name="logger">The logger to use.</param>
protected virtual void ValidateSqlQuery(
IEntityType entityType,
IDiagnosticsLogger<DbLoggerCategory.Model.Validation> logger)
{View on GitHub (pinned to dbf9771522)
Solutions
- Move the ToJson() up to the root complex property so the entire JSON subtree (entity root -> complex -> nested complex) is consistently JSON-mapped.
- If the outer complex must stay table-mapped, map the inner collection/entity to its own table or as owned entities rather than a nested JSON column.
- Restructure so only the entity-rooted complex type carries ToJson().
Example fix
// before - JSON nested inside a table-shared complex type
modelBuilder.Entity<Customer>().ComplexProperty(c => c.Contact, contact =>
{
// Contact is flattened to columns (no ToJson)
contact.OwnsOne(c => c.Preferences, prefs =>
{
prefs.ToJson("PrefsJson"); // throws: parent not JSON
});
});
// after - root the whole JSON subtree at the entity
modelBuilder.Entity<Customer>().ComplexProperty(c => c.Contact, contact =>
{
contact.ToJson("ContactJson");
contact.OwnsOne(c => c.Preferences, prefs => { });
}); Defensive patterns
Strategy: validation
Validate before calling
foreach (var et in context.Model.GetEntityTypes())
{
foreach (var cp in et.GetComplexProperties())
{
if (cp.ComplexType.IsMappedToJson()
&& !cp.DeclaringType.IsMappedToJson()
&& cp.DeclaringType is IComplexType)
{
// will throw (#36558) - move ToJson() to the root complex property.
}
}
} Prevention
- Root JSON columns at the entity, never at a nested complex type inside a table-shared one.
- When introducing ToJson(), apply it from the top of the subtree downward.
- Treat issue #36558 as the canonical reference for this constraint.
When it happens
Trigger: A nested complex property (declaring type is a complex type) configured with ToJson() while the outer complex type is mapped to columns (no ToJson on the root). Thrown at model validation.
Common situations: Marking only an inner complex property as JSON during a partial migration to JSON columns; building nested value-object structures and applying ToJson at the wrong level.
Related errors
- The property '{property}' on type '{type}' is mapped to a JS
- The key {keyProperties} on the entity type '{entityType}' ca
- The optional complex property '{type}.{property}' is mapped
- Complex property '{complexProperty}' cannot have both a JSON
- Complex property '{complexProperty}' cannot use 'HasJsonProp
AI-assisted analysis of dotnet/efcore@dbf9771522 (2026-08-06).
Data as JSON: /api/errors/ed8e622c8fd90983.
Report an issue: GitHub.