dotnet/efcore · error · InvalidOperationException

The index on the entity type ' ' cannot contain the complex…

Error message

The index {indexProperties} on the entity type '{entityType}' cannot contain the complex property '{property}' because it's mapped to multiple columns. Reference each scalar property of the complex type individually instead.

What it means

An index can reference a complex property as a single unit only when that complex type is mapped to JSON (one column). A non-JSON complex property fans out to multiple columns, so one index cannot represent it. The validator (ValidateIndexOnComplexProperty) finds the first non-JSON complex property in the index path and throws, telling you to reference each scalar sub-property individually.

Solutions

  1. Reference scalar sub-properties of the complex type individually: .HasIndex(e => e.Address!.ZipCode).
  2. If you genuinely want one index over the whole value object, map the complex type to JSON (.ToJson) so it occupies a single column.
  3. Split the index so each column is named explicitly.

Example fix

// before — indexing a non-JSON complex property -> [446]
modelBuilder.Entity<Customer>()
    .ComplexProperty(c => c.Address)
    .HasIndex(c => c.Address); // Address spans many columns

// after — index scalar sub-properties
modelBuilder.Entity<Customer>()
    .ComplexProperty(c => c.Address);
modelBuilder.Entity<Customer>().HasIndex(c => c.Address.ZipCode);
Defensive patterns

Strategy: validation

Validate before calling

// Before indexing a complex property, ensure it is JSON-mapped or index its scalar leaves.
static bool CanIndexComplexPropertyAsUnit(IReadOnlyComplexProperty cp)
    => cp.ComplexType.IsMappedToJson();

Type guard

static bool IsComplexPropertyJsonMapped(IReadOnlyComplexProperty cp)
    => cp.ComplexType.IsMappedToJson();

Prevention

When it happens

Trigger: Calling .HasIndex(e => e.Address) where Address is a complex property whose complex type is NOT mapped to JSON (it maps to multiple columns).

Common situations: Indexing a value-object/struct that is mapped to columns; misunderstanding complex types vs entities; copying a JSON-style index onto a column-mapped complex type.

Related errors


AI-assisted analysis of dotnet/efcore@3a2006ef56 (2026-08-11). Data as JSON: /api/errors/2921355b0183c327. Report an issue: GitHub.

Appendix: source

Thrown at src/EFCore.Relational/Infrastructure/RelationalModelValidator.cs:2778

        if (inJsonComplex)
        {
            return;
        }

        base.ValidateIndexProperty(index, property, logger);
    }

    /// <inheritdoc />
    protected override void ValidateIndexOnComplexProperty(
        IIndex index,
        IReadOnlyList<IComplexProperty> complexProperties,
        IDiagnosticsLogger<DbLoggerCategory.Model.Validation> logger)
    {
        var nonJsonComplexProperty = complexProperties.FirstOrDefault(cp => !cp.ComplexType.IsMappedToJson());
        if (nonJsonComplexProperty != null)
        {
            throw new InvalidOperationException(
                RelationalStrings.IndexOnNonJsonComplexProperty(
                    index.Properties.Format(),
                    index.DeclaringEntityType.DisplayName(),
                    nonJsonComplexProperty.Name));
        }

        if (index.IsUnique)
        {
            // Currently not supported. We have special logic for unique indexes in the update pipeline
            // and query that would need to be updated to support this.
            throw new InvalidOperationException(
                RelationalStrings.UniqueIndexOnComplexProperty(
                    index.Properties.Format(),
                    index.DeclaringEntityType.DisplayName(),
                    complexProperties[0].Name));
        }
    }

View on GitHub (pinned to 3a2006ef56)