{"record":{"id":"769b164b7bf8f33b","repo":"dotnet/efcore","slug":"a-partition-key-is-defined-on-entity-type-entity","errorCode":null,"errorMessage":"A partition key is defined on entity type '{entityType}', which inherits from '{baseEntityType}'. Partition keys must be defined on the root entity type of a hierarchy.","messagePattern":"A partition key is defined on entity type '(.+?)', which inherits from '(.+?)'\\. Partition keys must be defined on the root entity type of a hierarchy\\.","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"src/EFCore.Cosmos/Infrastructure/Internal/CosmosModelValidator.cs","lineNumber":458,"sourceCode":"        var idType = idProperty.GetTypeMapping().Converter?.ProviderClrType\n            ?? idProperty.ClrType;\n        if (idType != typeof(string))\n        {\n            throw new InvalidOperationException(\n                CosmosStrings.IdNonStringStoreType(idProperty.Name, entityType.DisplayName(), idType.ShortDisplayName()));\n        }\n\n        var partitionKeyPropertyNames = entityType.GetPartitionKeyPropertyNames();\n        if (partitionKeyPropertyNames.Count == 0)\n        {\n            logger.NoPartitionKeyDefined(entityType);\n        }\n        else\n        {\n            if (entityType.BaseType != null\n                && entityType.FindAnnotation(CosmosAnnotationNames.PartitionKeyNames)?.Value != null)\n            {\n                throw new InvalidOperationException(\n                    CosmosStrings.PartitionKeyNotOnRoot(entityType.DisplayName(), entityType.BaseType.DisplayName()));\n            }\n\n            foreach (var partitionKeyPropertyName in partitionKeyPropertyNames)\n            {\n                var partitionKey = entityType.FindProperty(partitionKeyPropertyName);\n                if (partitionKey == null)\n                {\n                    throw new InvalidOperationException(\n                        CosmosStrings.PartitionKeyMissingProperty(entityType.DisplayName(), partitionKeyPropertyName));\n                }\n\n                var partitionKeyType = (partitionKey.GetTypeMapping().Converter?.ProviderClrType\n                    ?? partitionKey.ClrType).UnwrapNullableType();\n                if (partitionKeyType != typeof(string)\n                    && !partitionKeyType.IsNumeric()\n                    && partitionKeyType != typeof(bool))\n                {","sourceCodeStart":440,"sourceCodeEnd":476,"githubUrl":"https://github.com/dotnet/efcore/blob/3a2006ef569de08368d59db5e1468aa8f407e4f8/src/EFCore.Cosmos/Infrastructure/Internal/CosmosModelValidator.cs#L440-L476","documentation":"Thrown when a partition key is configured on a derived entity type (one with a BaseType) rather than on the root of the hierarchy. Cosmos partition keys are a container-level concern and must be defined on the document-root entity type. The validator detects a non-null PartitionKeyNames annotation on a type whose BaseType is not null.","triggerScenarios":"Calling HasPartitionKey on a derived entity (an entity that participates in a TPH hierarchy as a non-root type). Fires during ValidateKeys at model validation time.","commonSituations":"Applying HasPartitionKey inside a per-derived-type IEntityTypeConfiguration; copying a config that worked for a standalone entity onto a hierarchy member; not realizing partition keys apply to the whole container.","solutions":["Move the HasPartitionKey call from the derived entity to the document-root entity type of the hierarchy.","If you use IEntityTypeConfiguration<T>, only register the partition-key configuration for the root type TRoot.","Remove any HasPartitionKey call on derived types and rely on the root configuration."],"exampleFix":"// before\nmodelBuilder.Entity<DerivedOrder>()   // : Order\n    .HasPartitionKey(o => o.TenantId);\n\n// after\nmodelBuilder.Entity<Order>()           // the root\n    .HasPartitionKey(o => o.TenantId);","handlingStrategy":"type-guard","validationCode":null,"typeGuard":"// Guard: only configure partition key when the type is the hierarchy root.\nstatic bool IsHierarchyRoot(Type t, IModel model)\n{\n    var et = model.FindEntityType(t);\n    return et is not null && et.BaseType is null;\n}\n\nif (IsHierarchyRoot(typeof(Order), modelBuilder.Model))\n    modelBuilder.Entity<Order>().HasPartitionKey(o => o.TenantId);","tryCatchPattern":null,"preventionTips":["Configure partition keys on the document root only.","Register IEntityTypeConfiguration<T> for the root type only when it includes HasPartitionKey.","Add a CI test asserting no derived type carries PartitionKeyNames."],"tags":["cosmos","model-validation","partition-key","hierarchy","configuration"],"backgroundTag":null,"analyzedSha":"3a2006ef569de08368d59db5e1468aa8f407e4f8","analyzedAt":"2026-08-11T23:42:04.146Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}