dotnet/efcore · error · InvalidOperationException
The index over properties
Error message
The index over properties '{properties}' is declared on owned type '{ownedEntityType}', which is mapped to container '{containerEntityType}'. Indexes that traverse owned types are not currently supported. What it means
Thrown when a regular (non-vector, non-full-text) index is declared on an owned entity type that is not a document root. Cosmos only allows indexes that traverse owned types if they are vector indexes or full-text indexes; regular property indexes must be declared on the document root. The validator walks the owned-navigation tree via EnumerateContainerIndexes and rejects any plain index whose declaring type is not a document root.
Solutions
- Move the HasIndex call to the document-root entity. If you need to query by a nested property, expose it on the root or restructure so the property lives on the root.
- If the index is actually for vector search, configure it as a vector index (HasVectorIndex) so the validator allows it on the owned path.
- If the index is for full-text search, mark it as a full-text index so it is exempted.
- Drop the index; Cosmos automatic indexing already covers individual nested paths by default.
Example fix
// before
modelBuilder.Entity<Order>().OwnsOne(o => o.Shipping, sb =>
{
sb.HasIndex(s => s.ZipCode); // regular index on owned type
});
// after - either move to root or rely on automatic indexing
modelBuilder.Entity<Order>().HasIndex(o => o.Shipping.ZipCode); // not valid either; instead, query via automatic indexing or denormalize
// Or simply remove the explicit index - Cosmos auto-indexes nested properties. Defensive patterns
Strategy: validation
Validate before calling
foreach (var et in dbContext.Model.GetEntityTypes())
{
foreach (var idx in et.GetIndexes())
{
if (!et.IsDocumentRoot()
&& idx.GetVectorIndexType() is null
&& idx.IsFullTextIndex() != true)
{
throw new InvalidOperationException($"Index on owned type {et.DisplayName()}");
}
}
} Prevention
- Declare regular indexes only on document-root entities.
- Use HasVectorIndex / full-text indexes for nested-owned-type scenarios.
- Prefer Cosmos automatic indexing for nested scalar queries.
When it happens
Trigger: Calling HasIndex on an owned entity configuration (OwnedTypeBuilder) for properties of the owned type. The error fires because the declaring entity type is not a document root and the index is neither a vector index nor a full-text index.
Common situations: Modeling an owned complex type and wanting to index one of its scalar properties; porting a relational model that used owned-type indexes verbatim to Cosmos; assuming Cosmos indexes nested JSON the same way as relational indexes owned tables.
Related errors
- Cosmos automatic-indexing configuration was set on entity…
- Cosmos automatic indexing is enabled for some entity types…
- The exception list configured for Cosmos automatic indexing…
- A full-text index is defined for
- A full-text index on
AI-assisted analysis of dotnet/efcore@3a2006ef56 (2026-08-11).
Data as JSON: /api/errors/b76d4114bd841baa.
Report an issue: GitHub.
Appendix: source
Thrown at src/EFCore.Cosmos/Infrastructure/Internal/CosmosModelValidator.cs:389
throw new InvalidOperationException(
CosmosStrings.InconsistentAutomaticIndexing(
container,
automaticIndexingOwner.DisplayName(),
entityType.DisplayName()));
}
}
}
// Walk the full owned/complex tree to surface every HasIndex declared in this container.
// Vector and full-text indexes are allowed to traverse owned types; only regular indexes are
// rejected
foreach (var (declaringEntityType, index) in EnumerateContainerIndexes(entityType))
{
if (!declaringEntityType.IsDocumentRoot()
&& index.GetVectorIndexType() == null
&& index.IsFullTextIndex() != true)
{
throw new InvalidOperationException(
CosmosStrings.IndexOnOwnedType(
string.Join(",", index.Properties.Select(e => e.Name)),
declaringEntityType.DisplayName(),
entityType.DisplayName()));
}
}
}
}
private static IEnumerable<(IEntityType DeclaringEntityType, IIndex Index)> EnumerateContainerIndexes(IEntityType root)
{
foreach (var index in root.GetIndexes())
{
yield return (root, index);
}
foreach (var ownedNav in root.GetNavigations()
.Where(n => n.ForeignKey.IsOwnership && !n.IsOnDependent && !n.TargetEntityType.IsDocumentRoot()))View on GitHub (pinned to 3a2006ef56)