dotnet/efcore · error · InvalidOperationException
A vector index on ' ' is defined over properties ` `. A…
Error message
A vector index on '{entityType}' is defined over properties `{properties}`. A vector index can only target a single property. What it means
Thrown when a vector index is defined over more than one property. Cosmos vector indexes target a single vector field, so EF Core rejects composite vector indexes. The validator checks index.Properties.Count and throws CompositeVectorIndex if it exceeds 1.
Solutions
- Split the composite into separate single-property vector indexes, one per vector field.
- If you intended a hybrid (vector + filter) index, drop the non-vector properties from the index definition - filter on them via the query instead.
- Keep regular indexes and vector indexes as separate HasIndex calls.
Example fix
// before
modelBuilder.Entity<Document>()
.HasIndex(d => new { d.TitleVector, d.BodyVector })
.HasVectorIndex(DistanceFunction.Cosine, 1536);
// after
modelBuilder.Entity<Document>().HasIndex(d => d.TitleVector).HasVectorIndex(DistanceFunction.Cosine, 1536);
modelBuilder.Entity<Document>().HasIndex(d => d.BodyVector).HasVectorIndex(DistanceFunction.Cosine, 1536); Defensive patterns
Strategy: validation
Validate before calling
foreach (var et in dbContext.Model.GetEntityTypes())
{
foreach (var idx in et.GetIndexes())
{
if (idx.GetVectorIndexType() is not null && idx.Properties.Count > 1)
throw new InvalidOperationException($"{et.DisplayName()} has a composite vector index");
}
} Prevention
- Define vector indexes over a single property each.
- Keep relational-style composite HasIndex expressions separate from vector indexes.
- Add a CI test asserting every vector index targets exactly one property.
When it happens
Trigger: Calling HasIndex(x => new { x.VecA, x.VecB }).HasVectorIndex(...) (a composite vector index) where two or more properties are included. Fires during ValidateVectorIndex for any index whose GetVectorIndexType() is non-null.
Common situations: Copy-pasting a composite relational index pattern and adding a vector-index call to it; building multi-vector search before realizing Cosmos supports only one vector per index; refactoring an index that grew to include a second vector property.
Related errors
- A full-text index is defined for
- A full-text index on
- A partition key is defined on entity type
- A vector index is defined for
- Both properties ' ' and ' ' on entity type ' ' are mapped…
AI-assisted analysis of dotnet/efcore@3a2006ef56 (2026-08-11).
Data as JSON: /api/errors/3528b7b620d21214.
Report an issue: GitHub.
Appendix: source
Thrown at src/EFCore.Cosmos/Infrastructure/Internal/CosmosModelValidator.cs:614
{
// Cosmos maps every property to JSON; no additional validation is needed here.
}
/// <summary>
/// This is an internal API that supports the Entity Framework Core infrastructure and not subject to
/// the same compatibility standards as public APIs. It may be changed or removed without notice in
/// any release. You should only use it directly in your code with extreme caution and knowing that
/// doing so can result in application failures when updating to a new Entity Framework Core release.
/// </summary>
protected virtual void ValidateVectorIndex(
IIndex index,
IDiagnosticsLogger<DbLoggerCategory.Model.Validation> logger)
{
var entityType = index.DeclaringEntityType;
if (index.Properties.Count > 1)
{
throw new InvalidOperationException(
CosmosStrings.CompositeVectorIndex(
entityType.DisplayName(),
string.Join(",", index.Properties.Select(e => e.Name))));
}
if (index.Properties[0] is not IProperty firstVectorIndexProperty
|| firstVectorIndexProperty.GetVectorDistanceFunction() == null
|| firstVectorIndexProperty.GetVectorDimensions() == null)
{
throw new InvalidOperationException(
CosmosStrings.VectorIndexOnNonVector(
entityType.DisplayName(),
index.Properties[0].Name));
}
}
/// <summary>
/// This is an internal API that supports the Entity Framework Core infrastructure and not subject toView on GitHub (pinned to 3a2006ef56)