dotnet/efcore · error · InvalidOperationException
Complex property ' ' cannot use 'HasJsonPropertyName()'…
Error message
Complex property '{complexProperty}' cannot use 'HasJsonPropertyName()' because it is not contained within a JSON-mapped type. Use 'ToJson()' to map the complex property to a JSON column, or ensure it is contained within a type that is mapped to JSON. What it means
ValidatePropertyMapping throws ComplexPropertyJsonPropertyNameWithoutJsonMapping when a complex property has HasJsonPropertyName configured but its declaring type is not itself mapped to JSON. HasJsonPropertyName only makes sense inside a containing JSON column; using it on a complex property whose owner is a regular table is meaningless, so the validator blocks it. The message directs the user to ToJson() or to relocate the property inside a JSON-mapped type.
Solutions
- If the owner is meant to be JSON, add ToJson() to the appropriate owning entity/complex property.
- Otherwise remove HasJsonPropertyName() and use HasColumnName() to control the flattened column name instead.
- Move the complex property under a JSON-mapped parent if it should indeed be a JSON sub-property.
Example fix
// before — Customer is a table, Address has a JSON property name
modelBuilder.Entity<Customer>()
.OwnsOne(c => c.Address, a => a.HasJsonPropertyName("addr")); // throws
// after — use a column name override for flattened mapping
modelBuilder.Entity<Customer>()
.OwnsOne(c => c.Address, a => a.Property(p => p.City).HasColumnName("address_city")); Defensive patterns
Strategy: validation
Validate before calling
if (complexProperty.GetJsonPropertyName() != null
&& !complexProperty.DeclaringType.IsMappedToJson())
throw new InvalidOperationException("HasJsonPropertyName requires the declaring type to be JSON-mapped."); Type guard
static bool HasJsonPropertyNameWithoutJsonParent(IComplexProperty cp)
=> cp.GetJsonPropertyName() != null && !cp.DeclaringType.IsMappedToJson(); Prevention
- Only use HasJsonPropertyName inside a JSON-mapped containing type.
- Use HasColumnName to override flattened column names on table-mapped complex properties.
- Move complex properties under a JSON-mapped parent if they should be JSON sub-properties.
When it happens
Trigger: Calling HasJsonPropertyName on a complex property whose DeclaringType.IsMappedToJson() is false — e.g. a top-level entity owns a complex property with HasJsonPropertyName but the entity is mapped to a table, not JSON.
Common situations: Misusing HasJsonPropertyName (a JSON-within-JSON API) as a column name override; configuring a complex property as if it were a JSON sub-property without ever marking the owner as JSON; scaffolding tools that emit HasJsonPropertyName unconditionally.
Related errors
- Complex property ' ' cannot have both a JSON column name ('…
- Complex property ' ' is mapped to JSON but its containing…
- The complex collection property
- The key on the entity type ' ' cannot be configured because…
- Both properties ' ' and ' ' on entity type ' ' are mapped…
AI-assisted analysis of dotnet/efcore@3a2006ef56 (2026-08-11).
Data as JSON: /api/errors/afd65db968c25d12.
Report an issue: GitHub.
Appendix: source
Thrown at src/EFCore.Relational/Infrastructure/RelationalModelValidator.cs:295
{
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(
$"{complexProperty.DeclaringType.DisplayName()}.{complexProperty.Name}",
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);View on GitHub (pinned to 3a2006ef56)