{"record":{"id":"3528b7b620d21214","repo":"dotnet/efcore","slug":"a-vector-index-on-entitytype-is-defined-over-p","errorCode":null,"errorMessage":"A vector index on '{entityType}' is defined over properties `{properties}`. A vector index can only target a single property.","messagePattern":"A vector index on '(.+?)' is defined over properties `(.+?)`\\. A vector index can only target a single property\\.","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"src/EFCore.Cosmos/Infrastructure/Internal/CosmosModelValidator.cs","lineNumber":614,"sourceCode":"    {\n        // Cosmos maps every property to JSON; no additional validation is needed here.\n    }\n\n    /// <summary>\n    ///     This is an internal API that supports the Entity Framework Core infrastructure and not subject to\n    ///     the same compatibility standards as public APIs. It may be changed or removed without notice in\n    ///     any release. You should only use it directly in your code with extreme caution and knowing that\n    ///     doing so can result in application failures when updating to a new Entity Framework Core release.\n    /// </summary>\n    protected virtual void ValidateVectorIndex(\n        IIndex index,\n        IDiagnosticsLogger<DbLoggerCategory.Model.Validation> logger)\n    {\n        var entityType = index.DeclaringEntityType;\n\n        if (index.Properties.Count > 1)\n        {\n            throw new InvalidOperationException(\n                CosmosStrings.CompositeVectorIndex(\n                    entityType.DisplayName(),\n                    string.Join(\",\", index.Properties.Select(e => e.Name))));\n        }\n\n        if (index.Properties[0] is not IProperty firstVectorIndexProperty\n            || firstVectorIndexProperty.GetVectorDistanceFunction() == null\n            || firstVectorIndexProperty.GetVectorDimensions() == null)\n        {\n            throw new InvalidOperationException(\n                CosmosStrings.VectorIndexOnNonVector(\n                    entityType.DisplayName(),\n                    index.Properties[0].Name));\n        }\n    }\n\n    /// <summary>\n    ///     This is an internal API that supports the Entity Framework Core infrastructure and not subject to","sourceCodeStart":596,"sourceCodeEnd":632,"githubUrl":"https://github.com/dotnet/efcore/blob/dbf9771522148d61a2467854921bd5dc6f6e6916/src/EFCore.Cosmos/Infrastructure/Internal/CosmosModelValidator.cs#L596-L632","documentation":"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.","triggerScenarios":"Declaring modelBuilder.Entity<E>().HasIndex(e => new { e.Vec1, e.Vec2 }).IsVectorIndex(...) or otherwise composing a vector index over multiple properties.","commonSituations":"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.","solutions":["Split the composite vector index into one single-property vector index per vector property.","Declare each vector index over exactly one property: HasIndex(e => e.Vec1).IsVectorIndex(Type, ...)."],"exampleFix":"// before\nmodelBuilder.Entity<Doc>()\n    .HasIndex(d => new { d.TitleVector, d.BodyVector })\n    .IsVectorIndex(VectorIndexType.DiskANN);\n\n// after\nmodelBuilder.Entity<Doc>().HasIndex(d => d.TitleVector).IsVectorIndex(VectorIndexType.DiskANN);\nmodelBuilder.Entity<Doc>().HasIndex(d => d.BodyVector).IsVectorIndex(VectorIndexType.DiskANN);","handlingStrategy":"validation","validationCode":"using var ctx = new MyContext();\nforeach (var e in ctx.Model.GetEntityTypes())\n{\n    foreach (var idx in e.GetDeclaredIndexes().Where(i => i.GetVectorIndexType() is not null))\n    {\n        Debug.Assert(idx.Properties.Count == 1, $\"{e.Name}: vector index over [{string.Join(\",\", idx.Properties.Select(p => p.Name))}] must target a single property\");\n    }\n}","typeGuard":null,"tryCatchPattern":"try { ctx.Model.GetModel(); }\ncatch (InvalidOperationException ex) when (ex.Message.Contains(\"vector index can only target a single property\"))\n{\n    logger.LogError(ex, \"A composite vector index was declared\");\n    throw;\n}","preventionTips":["Declare one vector index per vector property, never a composite.","Add a test asserting every vector index has exactly one property.","Do not reuse relational composite-index patterns for vector properties."],"tags":["cosmos","configuration","model-validation","vector-index"],"analyzedSha":"dbf9771522148d61a2467854921bd5dc6f6e6916","analyzedAt":"2026-08-06T20:46:03.226Z","schemaVersion":2},"datasetVersion":"2026-08-07T03:17:09.362Z"}