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
- Reference scalar sub-properties of the complex type individually: .HasIndex(e => e.Address!.ZipCode).
- If you genuinely want one index over the whole value object, map the complex type to JSON (.ToJson) so it occupies a single column.
- 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
- Prefer indexing scalar sub-properties of complex types over indexing the whole complex property.
- Map a complex type to JSON only if you genuinely need it as a single indexable unit.
- Add a test that builds the model to catch index-on-complex mistakes early.
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
- The index on the entity type ' ' cannot be configured…
- The index on the entity type ' ' cannot be configured…
- A full-text index is defined for
- A full-text index on
- A partition key is defined on entity type
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)