{"record":{"id":"567b2283ec143045","repo":"dotnet/efcore","slug":"the-index-indexproperties-on-the-entity-type-e-567b22","errorCode":null,"errorMessage":"The index {indexProperties} on the entity type '{entityType}' cannot be configured because its properties are mapped to different JSON columns ('{firstColumn}' and '{secondColumn}'). All leaves of a JSON-path index (an index whose properties traverse a complex collection) must be contained in a single JSON column.","messagePattern":"The index (.+?) on the entity type '(.+?)' cannot be configured because its properties are mapped to different JSON columns \\('(.+?)' and '(.+?)'\\)\\. All leaves of a JSON-path index \\(an index whose properties traverse a complex collection\\) must be contained in a single JSON column\\.","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"src/EFCore.Relational/Infrastructure/RelationalModelValidator.cs","lineNumber":2736,"sourceCode":"                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(),\n                        index.DeclaringEntityType.DisplayName(),\n                        firstContainer,\n                        container));\n            }\n        }\n    }\n\n    /// <inheritdoc />\n    protected override void ValidateIndexProperty(\n        IIndex index,\n        IPropertyBase property,\n        IDiagnosticsLogger<DbLoggerCategory.Model.Validation> logger)\n    {\n        // A property declared inside a JSON-mapped complex type is a valid index target: when the\n        // path traverses a collection the index is a JSON-path index (CollectionIndices is non-null,\n        // already enforced by Index construction); otherwise it's a scalar inside a JSON document.","sourceCodeStart":2718,"sourceCodeEnd":2754,"githubUrl":"https://github.com/dotnet/efcore/blob/3a2006ef569de08368d59db5e1468aa8f407e4f8/src/EFCore.Relational/Infrastructure/RelationalModelValidator.cs#L2718-L2754","documentation":"A single JSON-path index must keep ALL leaf properties inside ONE JSON column. The validator records the first property's container column name and throws as soon as a later property's container column differs. Splitting a composite index across two JSON documents cannot be expressed as one index.","triggerScenarios":"Building a composite .HasIndex((e) => new { e.Doc1.Foo, e.Doc2.Bar }) where Doc1 and Doc2 are two different JSON-mapped complex properties with different container column names.","commonSituations":"Indexing across two JSON columns; refactoring that split one JSON document into two; copy-paste of index definitions across entities with different JSON containers.","solutions":["Keep every property of the index within the same JSON container column.","Split the composite index into one index per JSON column so each index targets a single document.","If the properties really belong together, merge them into one JSON-mapped complex type."],"exampleFix":"// before — leaves in two different JSON columns -> [445]\nmodelBuilder.Entity<Record>()\n    .OwnsOne(r => r.Meta, m => m.ToJson(\"meta\"))\n    .OwnsOne(r => r.Body, b => b.ToJson(\"body\"))\n    .HasIndex(r => new { r.Meta!.Tag, r.Body!.Kind });\n\n// after — one index per JSON column\nmodelBuilder.Entity<Record>()\n    .OwnsOne(r => r.Meta, m => m.ToJson(\"meta\"))\n    .OwnsOne(r => r.Body, b => b.ToJson(\"body\"));\nmodelBuilder.Entity<Record>().OwnsOne(r => r.Meta).HasIndex(m => m.Tag);\nmodelBuilder.Entity<Record>().OwnsOne(r => r.Body).HasIndex(b => b.Kind);","handlingStrategy":"validation","validationCode":"// All leaves of a JSON-path index must share one container column.\nstatic bool IndexUsesSingleJsonContainer(IIndex index)\n{\n    string? first = null;\n    foreach (var p in index.Properties)\n    {\n        string? container = p.DeclaringType is IReadOnlyComplexType ct && ct.IsMappedToJson() ? ct.GetContainerColumnName()\n            : p is IReadOnlyComplexProperty cp && cp.ComplexType.IsMappedToJson() ? cp.ComplexType.GetContainerColumnName()\n            : null;\n        if (container is null) continue;\n        if (first is null) first = container;\n        else if (first != container) return false;\n    }\n    return true;\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Keep composite JSON indexes within a single JSON column.","Split cross-column composite indexes into one index per JSON document.","Document which JSON column each index targets to prevent regressions."],"tags":["json","complex-types","indexes","model-validation"],"backgroundTag":null,"analyzedSha":"3a2006ef569de08368d59db5e1468aa8f407e4f8","analyzedAt":"2026-08-11T23:42:04.146Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}