{"record":{"id":"b76d4114bd841baa","repo":"dotnet/efcore","slug":"the-index-over-properties-properties-is-declar","errorCode":null,"errorMessage":"The index over properties '{properties}' is declared on owned type '{ownedEntityType}', which is mapped to container '{containerEntityType}'. Indexes that traverse owned types are not currently supported.","messagePattern":"The index over properties '(.+?)' is declared on owned type '(.+?)', which is mapped to container '(.+?)'\\. Indexes that traverse owned types are not currently supported\\.","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"src/EFCore.Cosmos/Infrastructure/Internal/CosmosModelValidator.cs","lineNumber":389,"sourceCode":"                        throw new InvalidOperationException(\n                            CosmosStrings.InconsistentAutomaticIndexing(\n                                container,\n                                automaticIndexingOwner.DisplayName(),\n                                entityType.DisplayName()));\n                    }\n                }\n            }\n\n            // Walk the full owned/complex tree to surface every HasIndex declared in this container.\n            // Vector and full-text indexes are allowed to traverse owned types; only regular indexes are\n            // rejected\n            foreach (var (declaringEntityType, index) in EnumerateContainerIndexes(entityType))\n            {\n                if (!declaringEntityType.IsDocumentRoot()\n                    && index.GetVectorIndexType() == null\n                    && index.IsFullTextIndex() != true)\n                {\n                    throw new InvalidOperationException(\n                        CosmosStrings.IndexOnOwnedType(\n                            string.Join(\",\", index.Properties.Select(e => e.Name)),\n                            declaringEntityType.DisplayName(),\n                            entityType.DisplayName()));\n                }\n            }\n        }\n    }\n\n    private static IEnumerable<(IEntityType DeclaringEntityType, IIndex Index)> EnumerateContainerIndexes(IEntityType root)\n    {\n        foreach (var index in root.GetIndexes())\n        {\n            yield return (root, index);\n        }\n\n        foreach (var ownedNav in root.GetNavigations()\n                     .Where(n => n.ForeignKey.IsOwnership && !n.IsOnDependent && !n.TargetEntityType.IsDocumentRoot()))","sourceCodeStart":371,"sourceCodeEnd":407,"githubUrl":"https://github.com/dotnet/efcore/blob/3a2006ef569de08368d59db5e1468aa8f407e4f8/src/EFCore.Cosmos/Infrastructure/Internal/CosmosModelValidator.cs#L371-L407","documentation":"Thrown when a regular (non-vector, non-full-text) index is declared on an owned entity type that is not a document root. Cosmos only allows indexes that traverse owned types if they are vector indexes or full-text indexes; regular property indexes must be declared on the document root. The validator walks the owned-navigation tree via EnumerateContainerIndexes and rejects any plain index whose declaring type is not a document root.","triggerScenarios":"Calling HasIndex on an owned entity configuration (OwnedTypeBuilder) for properties of the owned type. The error fires because the declaring entity type is not a document root and the index is neither a vector index nor a full-text index.","commonSituations":"Modeling an owned complex type and wanting to index one of its scalar properties; porting a relational model that used owned-type indexes verbatim to Cosmos; assuming Cosmos indexes nested JSON the same way as relational indexes owned tables.","solutions":["Move the HasIndex call to the document-root entity. If you need to query by a nested property, expose it on the root or restructure so the property lives on the root.","If the index is actually for vector search, configure it as a vector index (HasVectorIndex) so the validator allows it on the owned path.","If the index is for full-text search, mark it as a full-text index so it is exempted.","Drop the index; Cosmos automatic indexing already covers individual nested paths by default."],"exampleFix":"// before\nmodelBuilder.Entity<Order>().OwnsOne(o => o.Shipping, sb =>\n{\n    sb.HasIndex(s => s.ZipCode); // regular index on owned type\n});\n\n// after - either move to root or rely on automatic indexing\nmodelBuilder.Entity<Order>().HasIndex(o => o.Shipping.ZipCode); // not valid either; instead, query via automatic indexing or denormalize\n// Or simply remove the explicit index - Cosmos auto-indexes nested properties.","handlingStrategy":"validation","validationCode":"foreach (var et in dbContext.Model.GetEntityTypes())\n{\n    foreach (var idx in et.GetIndexes())\n    {\n        if (!et.IsDocumentRoot()\n            && idx.GetVectorIndexType() is null\n            && idx.IsFullTextIndex() != true)\n        {\n            throw new InvalidOperationException($\"Index on owned type {et.DisplayName()}\");\n        }\n    }\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Declare regular indexes only on document-root entities.","Use HasVectorIndex / full-text indexes for nested-owned-type scenarios.","Prefer Cosmos automatic indexing for nested scalar queries."],"tags":["cosmos","model-validation","indexing","owned-types","configuration"],"backgroundTag":null,"analyzedSha":"3a2006ef569de08368d59db5e1468aa8f407e4f8","analyzedAt":"2026-08-11T23:42:04.146Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}