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

CosmosClientWrapper throws CompositeVectorIndex when building container indexing policy and encounters a vector index whose index.Properties contains more than one property. Cosmos DB vector indexes must target exactly one path; composite vector indexes are not supported.

Solutions

  1. Define the vector index over exactly one property.
  2. Define a separate single-property vector index for each vector property.

Example fix

// before
modelBuilder.Entity<Item>()
    .HasIndex(x => new { x.Embedding1, x.Embedding2 })
    .IsVectorIndex(VectorIndexType.DiskANN);

// after - one vector index per property
modelBuilder.Entity<Item>().HasIndex(x => x.Embedding1).IsVectorIndex(VectorIndexType.DiskANN);
modelBuilder.Entity<Item>().HasIndex(x => x.Embedding2).IsVectorIndex(VectorIndexType.DiskANN);
Defensive patterns

Strategy: validation

Validate before calling

// At model build, assert vector indexes target exactly one property.
foreach (var idx in entityType.GetIndexes())
{
    if (idx.GetVectorIndexType() is not null && idx.Properties.Count > 1)
        throw new InvalidOperationException($"Vector index on {entityType.DisplayName()} targets multiple properties.");
}

Type guard

static bool IsSinglePropertyVectorIndex(IIndex idx) => idx.GetVectorIndexType() is not null && idx.Properties.Count == 1;

Prevention

When it happens

Trigger: Defining an index over multiple properties and marking it as a vector index, e.g. modelBuilder.Entity<T>().HasIndex(x => new { x.A, x.B }).IsVectorIndex(...).

Common situations: Bulk-applying the same index configuration to multi-property indexes; copy-pasting a composite index definition and adding IsVectorIndex.

Related errors


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

Appendix: 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 3a2006ef56)