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

  1. If the owner is meant to be JSON, add ToJson() to the appropriate owning entity/complex property.
  2. Otherwise remove HasJsonPropertyName() and use HasColumnName() to control the flattened column name instead.
  3. 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

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


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)