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

Thrown by ValidateVectorIndex (reached via ValidateIndex when index.GetVectorIndexType() != null) when the vector index spans more than one property. Azure Cosmos DB vector indexes target a single vector property, so a composite vector index is rejected at model validation.

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 to

View on GitHub (pinned to dbf9771522)

Solutions

  1. Split the composite vector index into one single-property vector index per vector property.
  2. Declare each vector index over exactly one property: HasIndex(e => e.Vec1).IsVectorIndex(Type, ...).

Example fix

// before
modelBuilder.Entity<Doc>()
    .HasIndex(d => new { d.TitleVector, d.BodyVector })
    .IsVectorIndex(VectorIndexType.DiskANN);

// after
modelBuilder.Entity<Doc>().HasIndex(d => d.TitleVector).IsVectorIndex(VectorIndexType.DiskANN);
modelBuilder.Entity<Doc>().HasIndex(d => d.BodyVector).IsVectorIndex(VectorIndexType.DiskANN);
Defensive patterns

Strategy: validation

Validate before calling

using var ctx = new MyContext();
foreach (var e in ctx.Model.GetEntityTypes())
{
    foreach (var idx in e.GetDeclaredIndexes().Where(i => i.GetVectorIndexType() is not null))
    {
        Debug.Assert(idx.Properties.Count == 1, $"{e.Name}: vector index over [{string.Join(",", idx.Properties.Select(p => p.Name))}] must target a single property");
    }
}

Try / catch

try { ctx.Model.GetModel(); }
catch (InvalidOperationException ex) when (ex.Message.Contains("vector index can only target a single property"))
{
    logger.LogError(ex, "A composite vector index was declared");
    throw;
}

Prevention

When it happens

Trigger: Declaring modelBuilder.Entity<E>().HasIndex(e => new { e.Vec1, e.Vec2 }).IsVectorIndex(...) or otherwise composing a vector index over multiple properties.

Common situations: Copying a composite relational index pattern onto vector properties; attempting to index multiple embeddings in one index; misunderstanding that each vector index is single-property.

Related errors


AI-assisted analysis of dotnet/efcore@dbf9771522 (2026-08-06). Data as JSON: /api/errors/3528b7b620d21214. Report an issue: GitHub.