dotnet/efcore · error · InvalidOperationException
A vector index on '{entityType}' is defined over properties
Error message
A vector index on '{entityType}' is defined over properties `{properties}`. A vector index can only target a single property. What it means
Azure Cosmos DB vector indexes can only be defined over a single property path. During container creation (CosmosClientWrapper.cs:183-189), EF Core iterates all indexes and rejects any index whose GetVectorIndexType() is non-null and whose Properties.Count exceeds 1. A composite vector index has no meaning in the Cosmos indexing policy schema.
Source
Thrown at src/EFCore.Cosmos/Storage/Internal/CosmosClientWrapper.cs:185
{
var (parameters, wrapper) = parametersTuple;
var partitionKeyPaths = parameters.PartitionKeyStoreNames.Select(e => "/" + e).ToList();
var vectorIndexes = new Collection<VectorIndexPath>();
var fullTextIndexPaths = new Collection<FullTextIndexPath>();
var includedPaths = new Collection<IncludedPath>();
var conventionIncludedPaths = new Collection<IncludedPath>();
var compositeIndexes = new Collection<Collection<CompositePath>>();
var seenIncludedPaths = new HashSet<string>();
var seenCompositeIndexes = new HashSet<string>();
foreach (var index in parameters.Indexes)
{
var vectorIndexType = index.GetVectorIndexType();
if (vectorIndexType != null)
{
if (index.Properties.Count > 1)
{
throw new InvalidOperationException(
CosmosStrings.CompositeVectorIndex(
index.DeclaringEntityType.DisplayName(),
string.Join(",", index.Properties.Select(e => e.Name))));
}
vectorIndexes.Add(
new VectorIndexPath { Path = GetJsonPropertyPathFromRoot(index.Properties[0]), Type = vectorIndexType.Value });
continue;
}
if (index.IsFullTextIndex() == true)
{
if (index.Properties.Count > 1)
{
throw new InvalidOperationException(
CosmosStrings.CompositeFullTextIndex(
index.DeclaringEntityType.DisplayName(),
string.Join(",", index.Properties.Select(e => e.Name))));View on GitHub (pinned to dbf9771522)
Solutions
- Define the vector index on a single property: modelBuilder.Entity<T>().HasIndex(x => x.Embedding).ForCosmos().IsVectorIndex(VectorIndexType.DiskANN).
- If you need a separate index for another property, declare it as its own single-property index.
- Re-run EnsureCreatedAsync (or recreate the container) after fixing the model.
Example fix
// before
modelBuilder.Entity<Article>()
.HasIndex(a => new { a.Embedding, a.Category })
.ForCosmos()
.IsVectorIndex(VectorIndexType.DiskANN);
// after
modelBuilder.Entity<Article>()
.HasIndex(a => a.Embedding)
.ForCosmos()
.IsVectorIndex(VectorIndexType.DiskANN); Defensive patterns
Strategy: validation
Validate before calling
// Validate at model finalization that no vector index spans multiple properties.
foreach (var entityType in model.GetEntityTypes())
{
foreach (var index in entityType.GetIndexes())
{
if (index.GetVectorIndexType() is not null && index.Properties.Count > 1)
throw new InvalidOperationException($"Vector index on {entityType.DisplayName()} has multiple properties.");
}
} Prevention
- Define vector indexes on a single property using HasIndex(x => x.Property), never an anonymous composite.
- Review all ForCosmos().IsVectorIndex() calls during code review.
- Add a model-validation test that checks vector indexes have exactly one property.
When it happens
Trigger: Configuring an index with multiple properties and marking it as a vector index, e.g. modelBuilder.Entity<T>().HasIndex([x => x.Embedding, x => x.Other]).ForCosmos().IsVectorIndex(VectorIndexType.DiskANN). This fires at container-creation time (EnsureCreatedAsync/EnsureCreated), not at model validation.
Common situations: Copy-pasting a composite index definition and adding IsVectorIndex() to it. Accidentally including a second property (like a partition key) in a vector index definition. Migrating from relational where composite indexes are common.
Related errors
- A full-text index on '{entityType}' is defined over multiple
- Creating a container with full-text search or vector propert
- The requested configuration is not stored in the read-optimi
- The value '{value}' provided for argument '{argumentName}' m
- The '{parameter}' value passed to '{methodName}' must be a c
AI-assisted analysis of dotnet/efcore@dbf9771522 (2026-08-06).
Data as JSON: /api/errors/96f7491aa4a92a05.
Report an issue: GitHub.