{"record":{"id":"5fa04bcdfec6846a","repo":"dotnet/efcore","slug":"the-index-indexproperties-on-the-entity-type-e","errorCode":null,"errorMessage":"The index {indexProperties} on the entity type '{entityType}' cannot be configured because its property '{property}' traverses a complex collection but is not mapped to a JSON column.","messagePattern":"The index (.+?) on the entity type '(.+?)' cannot be configured because its property '(.+?)' traverses a complex collection but is not mapped to a JSON column\\.","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"src/EFCore.Relational/Infrastructure/RelationalModelValidator.cs","lineNumber":2720,"sourceCode":"        {\n            var property = index.Properties[i];\n\n            // Only properties mapped inside a JSON container matter here. Mixed JSON / non-JSON indexes\n            // are rejected earlier by ValidateIndexPropertyMapping.\n            var container = property.DeclaringType is IReadOnlyComplexType complexType && complexType.IsMappedToJson()\n                ? complexType.GetContainerColumnName()\n                : property is IReadOnlyComplexProperty complexProperty && complexProperty.ComplexType.IsMappedToJson()\n                    ? complexProperty.ComplexType.GetContainerColumnName()\n                    : null;\n\n            if (container is null)\n            {\n                // Not a JSON-contained property. If this position carries a non-null collection-indices\n                // entry (i.e., the path traverses a complex collection but doesn't end in JSON), the\n                // index identity points at a JSON path that has no JSON container — that's invalid.\n                if (index.CollectionIndices?[i] is not null)\n                {\n                    throw new InvalidOperationException(\n                        RelationalStrings.JsonPathIndexPropertyMissingJsonColumn(\n                            index.Properties.Format(),\n                            index.DeclaringEntityType.DisplayName(),\n                            property.Name));\n                }\n\n                continue;\n            }\n\n            if (firstContainer is null)\n            {\n                firstContainer = container;\n            }\n            else if (!string.Equals(firstContainer, container, StringComparison.Ordinal))\n            {\n                throw new InvalidOperationException(\n                    RelationalStrings.JsonPathIndexPropertiesInDifferentJsonColumns(\n                        index.Properties.Format(),","sourceCodeStart":2702,"sourceCodeEnd":2738,"githubUrl":"https://github.com/dotnet/efcore/blob/dbf9771522148d61a2467854921bd5dc6f6e6916/src/EFCore.Relational/Infrastructure/RelationalModelValidator.cs#L2702-L2738","documentation":"Thrown during index validation when an index property path traverses a complex collection (CollectionIndices[i] is non-null) but the property at that position is not inside a JSON-mapped column. EF can only create a JSON-path index over properties inside a JSON document column; a complex collection without JSON mapping produces no addressable single column. See RelationalModelValidator.cs:2713-2725 where container is null but CollectionIndices entry is non-null.","triggerScenarios":"Creating an index over a property inside a complex property that is a collection (HasIndex with a lambda traversing a collection) where the complex type is NOT configured with ToJson. The index builder records CollectionIndices, but GetContainerColumnName returns null because IsMappedToJson() is false.","commonSituations":"Indexing a nested property inside a complex collection (e.g., HasIndex(e => e.Items.First().Name)) without configuring the complex property with .ToJson(\"column_name\"). Attempting to create database indexes across table-per-column complex type collections.","solutions":["Configure the complex collection property to be mapped to JSON using .ToJson(\"ColumnName\") so the index becomes a valid JSON-path index.","Remove the index that traverses the complex collection — indexes over complex collections that aren't JSON-mapped are not supported.","Denormalize the indexed scalar out of the complex collection into a top-level column on the entity and index that instead."],"exampleFix":"// before: complex collection without JSON mapping, index traverses it\nmodelBuilder.Entity<Customer>()\n    .ComplexProperty(c => c.Addresses, ab =>\n    {\n        ab.IsCollection();\n    });\nmodelBuilder.Entity<Customer>().HasIndex(\"Addresses.ZipCode\"); // throws\n\n// after: map the complex collection to JSON\nmodelBuilder.Entity<Customer>()\n    .ComplexProperty(c => c.Addresses, ab =>\n    {\n        ab.ToJson(\"addresses\");\n    });\nmodelBuilder.Entity<Customer>().HasIndex(\"Addresses.ZipCode\");","handlingStrategy":"validation","validationCode":"// Ensure complex collections used in indexes are mapped to JSON.\nforeach (var index in modelBuilder.Model.GetEntityTypes().SelectMany(e => e.GetIndexes()))\n{\n    if (index.CollectionIndices is null) continue;\n    for (var i = 0; i < index.Properties.Count; i++)\n    {\n        if (index.CollectionIndices[i] is null) continue;\n        var prop = index.Properties[i];\n        var container = prop.DeclaringType is IComplexType ct && ct.IsMappedToJson()\n            ? ct.GetContainerColumnName()\n            : (prop is IComplexProperty cp && cp.ComplexType.IsMappedToJson()\n                ? cp.ComplexType.GetContainerColumnName() : null);\n        if (container is null)\n            Console.WriteLine($\"Index property '{prop.Name}' traverses a complex collection but has no JSON column — add ToJson().\");\n    }\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Always call .ToJson(\"column\") when defining complex collection properties that will be indexed.","Avoid indexing properties inside complex collections unless they are JSON-mapped.","Write a model validation unit test that checks all indexes against their JSON mapping."],"tags":["index","json","complex-collection","model-validation"],"analyzedSha":"dbf9771522148d61a2467854921bd5dc6f6e6916","analyzedAt":"2026-08-06T20:46:03.226Z","schemaVersion":2},"datasetVersion":"2026-08-07T03:17:09.362Z"}