{"record":{"id":"1b11f7ba30aad902","repo":"dotnet/efcore","slug":"trigger-trigger-is-defined-on-entity-type-en","errorCode":null,"errorMessage":"Trigger '{trigger}' is defined on entity type '{entityType}' which inherits from '{baseType}'. Triggers can only be defined on root entity types.","messagePattern":"Trigger '(.+?)' is defined on entity type '(.+?)' which inherits from '(.+?)'\\. Triggers can only be defined on root entity types\\.","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"src/EFCore.Cosmos/Infrastructure/Internal/CosmosModelValidator.cs","lineNumber":784,"sourceCode":"        ValidateTriggerOnRootType(trigger, entityType, logger);\n        ValidateTriggerType(trigger, entityType, logger);\n        ValidateTriggerOperation(trigger, entityType, logger);\n    }\n\n    /// <summary>\n    ///     This is an internal API that supports the Entity Framework Core infrastructure and not subject to\n    ///     the same compatibility standards as public APIs. It may be changed or removed without notice in\n    ///     any release. You should only use it directly in your code with extreme caution and knowing that\n    ///     doing so can result in application failures when updating to a new Entity Framework Core release.\n    /// </summary>\n    protected virtual void ValidateTriggerOnRootType(\n        ITrigger trigger,\n        IEntityType entityType,\n        IDiagnosticsLogger<DbLoggerCategory.Model.Validation> logger)\n    {\n        if (entityType.BaseType != null)\n        {\n            throw new InvalidOperationException(\n                CosmosStrings.TriggerOnDerivedType(trigger.ModelName, entityType.DisplayName(), entityType.BaseType.DisplayName()));\n        }\n    }\n\n    /// <summary>\n    ///     This is an internal API that supports the Entity Framework Core infrastructure and not subject to\n    ///     the same compatibility standards as public APIs. It may be changed or removed without notice in\n    ///     any release. You should only use it directly in your code with extreme caution and knowing that\n    ///     doing so can result in application failures when updating to a new Entity Framework Core release.\n    /// </summary>\n    protected virtual void ValidateTriggerType(\n        ITrigger trigger,\n        IEntityType entityType,\n        IDiagnosticsLogger<DbLoggerCategory.Model.Validation> logger)\n    {\n        if (trigger.GetTriggerType() == null)\n        {\n            throw new InvalidOperationException(","sourceCodeStart":766,"sourceCodeEnd":802,"githubUrl":"https://github.com/dotnet/efcore/blob/dbf9771522148d61a2467854921bd5dc6f6e6916/src/EFCore.Cosmos/Infrastructure/Internal/CosmosModelValidator.cs#L766-L802","documentation":"Thrown by CosmosModelValidator.ValidateTriggerOnRootType when entityType.BaseType != null. Cosmos DB pre-triggers must be attached to the container that owns the root entity type; attaching a trigger to a derived (TPH/branch) entity type has no Cosmos-side meaning, so EF Core requires triggers only on the root of a hierarchy.","triggerScenarios":"Calling modelBuilder.Entity<DerivedType>().HasTrigger(...) or .Trigger(t => ...) where DerivedType inherits from a base entity type configured in the same model.","commonSituations":"Defining triggers per derived class in a TPH hierarchy expecting per-type trigger behavior. Moving trigger configuration from the base type to derived types during a refactor.","solutions":["Move the HasTrigger / Trigger configuration onto the root base entity type of the hierarchy.","If per-derived-type behavior is needed, drive it from the trigger body using runtime type checks rather than defining separate Cosmos triggers per derived type."],"exampleFix":"// before\nmodelBuilder.Entity<Manager>() // Manager : Employee\n    .HasTrigger(\"onManagerCreate\");\n\n// after\nmodelBuilder.Entity<Employee>() // root type\n    .HasTrigger(\"onEmployeeCreate\");","handlingStrategy":"validation","validationCode":"foreach (var et in modelBuilder.Model.GetEntityTypes())\n{\n    foreach (var trigger in et.GetTriggers())\n    {\n        if (et.BaseType is not null)\n            throw new InvalidOperationException($\"Trigger {trigger.ModelName} on derived type {et.DisplayName()}; move to root {et.GetRootType().DisplayName()}.\");\n    }\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Define all HasTrigger configuration on root entity types only.","In TPH hierarchies, drive per-type behavior from inside the trigger body, not from per-type trigger definitions."],"tags":["cosmos","ef-core","model-validation","triggers","inheritance"],"analyzedSha":"dbf9771522148d61a2467854921bd5dc6f6e6916","analyzedAt":"2026-08-06T20:46:03.226Z","schemaVersion":2},"datasetVersion":"2026-08-07T03:17:09.362Z"}