{"record":{"id":"2921355b0183c327","repo":"dotnet/efcore","slug":"the-index-indexproperties-on-the-entity-type-e-292135","errorCode":null,"errorMessage":"The index {indexProperties} on the entity type '{entityType}' cannot contain the complex property '{property}' because it's mapped to multiple columns. Reference each scalar property of the complex type individually instead.","messagePattern":"The index (.+?) on the entity type '(.+?)' cannot contain the complex property '(.+?)' because it's mapped to multiple columns\\. Reference each scalar property of the complex type individually instead\\.","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"src/EFCore.Relational/Infrastructure/RelationalModelValidator.cs","lineNumber":2778,"sourceCode":"\n        if (inJsonComplex)\n        {\n            return;\n        }\n\n        base.ValidateIndexProperty(index, property, logger);\n    }\n\n    /// <inheritdoc />\n    protected override void ValidateIndexOnComplexProperty(\n        IIndex index,\n        IReadOnlyList<IComplexProperty> complexProperties,\n        IDiagnosticsLogger<DbLoggerCategory.Model.Validation> logger)\n    {\n        var nonJsonComplexProperty = complexProperties.FirstOrDefault(cp => !cp.ComplexType.IsMappedToJson());\n        if (nonJsonComplexProperty != null)\n        {\n            throw new InvalidOperationException(\n                RelationalStrings.IndexOnNonJsonComplexProperty(\n                    index.Properties.Format(),\n                    index.DeclaringEntityType.DisplayName(),\n                    nonJsonComplexProperty.Name));\n        }\n\n        if (index.IsUnique)\n        {\n            // Currently not supported. We have special logic for unique indexes in the update pipeline\n            // and query that would need to be updated to support this.\n            throw new InvalidOperationException(\n                RelationalStrings.UniqueIndexOnComplexProperty(\n                    index.Properties.Format(),\n                    index.DeclaringEntityType.DisplayName(),\n                    complexProperties[0].Name));\n        }\n    }\n","sourceCodeStart":2760,"sourceCodeEnd":2796,"githubUrl":"https://github.com/dotnet/efcore/blob/dbf9771522148d61a2467854921bd5dc6f6e6916/src/EFCore.Relational/Infrastructure/RelationalModelValidator.cs#L2760-L2796","documentation":"Thrown by ValidateIndexOnComplexProperty (RelationalModelValidator.cs:2775-2783) when an index directly references a complex property (not a scalar leaf inside it) that is not mapped to JSON. A non-JSON complex property expands to multiple columns, so it cannot be part of an index as a single entity — you must reference each scalar property individually.","triggerScenarios":"Calling HasIndex with a lambda that selects a complex property itself (not a scalar inside it), where the complex property is configured with the default table-per-column mapping (not ToJson). The validator finds the first complex property in the path whose ComplexType.IsMappedToJson() is false.","commonSituations":"Indexing e => e.Address (a complex property/value object) instead of e => e.Address.City. The developer expects EF to index 'the address' but EF needs a concrete scalar column.","solutions":["Replace the complex property in the index with its individual scalar properties (e.g., HasIndex(e => e.Address.City, e => e.Address.ZipCode)).","If you want the whole complex value indexed as JSON, map the complex property with ToJson and then index a leaf inside it."],"exampleFix":"// before: indexing the complex property itself\nmodelBuilder.Entity<Customer>()\n    .ComplexProperty(c => c.Address);\nmodelBuilder.Entity<Customer>().HasIndex(c => c.Address); // throws\n\n// after: index individual scalar properties\nmodelBuilder.Entity<Customer>().HasIndex(c => new { c.Address.City, c.Address.ZipCode });","handlingStrategy":"validation","validationCode":"// Detect indexes that reference a non-JSON complex property directly.\nforeach (var index in modelBuilder.Model.GetEntityTypes().SelectMany(e => e.GetDeclaredIndexes()))\n{\n    foreach (var prop in index.Properties)\n    {\n        if (prop is IComplexProperty cp && !cp.ComplexType.IsMappedToJson())\n            Console.WriteLine($\"Index on {index.DeclaringEntityType.DisplayName()} references complex property '{cp.Name}' — index scalar leaves instead.\");\n    }\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Never pass a complex property directly to HasIndex; always select scalar leaf properties.","Use strongly-typed lambda HasIndex(e => new { e.Address.City }) instead of string-based APIs to get compiler errors."],"tags":["index","complex-property","model-validation"],"analyzedSha":"dbf9771522148d61a2467854921bd5dc6f6e6916","analyzedAt":"2026-08-06T20:46:03.226Z","schemaVersion":2},"datasetVersion":"2026-08-07T03:17:09.362Z"}