{"record":{"id":"26ee8a2590bd1f6d","repo":"dotnet/efcore","slug":"trigger-trigger-on-entity-type-entitytype-26ee8a","errorCode":null,"errorMessage":"Trigger '{trigger}' on entity type '{entityType}' does not have a trigger operation configured. Use 'HasTriggerOperation()' to configure the trigger operation.","messagePattern":"Trigger '(.+?)' on entity type '(.+?)' does not have a trigger operation configured\\. Use 'HasTriggerOperation\\(\\)' to configure the trigger operation\\.","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"src/EFCore.Cosmos/Infrastructure/Internal/CosmosModelValidator.cs","lineNumber":820,"sourceCode":"            throw new InvalidOperationException(\n                CosmosStrings.TriggerMissingType(trigger.ModelName, entityType.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 ValidateTriggerOperation(\n        ITrigger trigger,\n        IEntityType entityType,\n        IDiagnosticsLogger<DbLoggerCategory.Model.Validation> logger)\n    {\n        if (trigger.GetTriggerOperation() == null)\n        {\n            throw new InvalidOperationException(\n                CosmosStrings.TriggerMissingOperation(trigger.ModelName, entityType.DisplayName()));\n        }\n    }\n}\n","sourceCodeStart":802,"sourceCodeEnd":825,"githubUrl":"https://github.com/dotnet/efcore/blob/3a2006ef569de08368d59db5e1468aa8f407e4f8/src/EFCore.Cosmos/Infrastructure/Internal/CosmosModelValidator.cs#L802-L825","documentation":"Thrown by CosmosModelValidator.ValidateTriggerOperation when trigger.GetTriggerOperation() returns null. Besides a TriggerType, every Cosmos trigger must declare a TriggerOperation (Create/Replace/Delete/All) via CosmosTriggerBuilderExtensions.HasTriggerOperation.","triggerScenarios":"Calling HasTrigger(...) and HasTriggerType(...) but never chaining .HasTriggerOperation(TriggerOperation.Create|Replace|Delete|All).","commonSituations":"Setting only the type and assuming a default operation; partial copy of trigger config; refactoring away the operation line.","solutions":["Chain .HasTriggerOperation(TriggerOperation.All) (or Create/Replace/Delete as appropriate) onto the trigger builder.","Verify the builder is non-null before chaining.","Re-validate the model to confirm both TriggerType and TriggerOperation are set."],"exampleFix":"// before\nmodelBuilder.Entity<Doc>()\n    .HasTrigger(\"ValidateDoc\")!\n    .HasTriggerType(TriggerType.Pre);\n\n// after\nmodelBuilder.Entity<Doc>()\n    .HasTrigger(\"ValidateDoc\")!\n    .HasTriggerType(TriggerType.Pre)\n    .HasTriggerOperation(TriggerOperation.Create);","handlingStrategy":"validation","validationCode":"// Ensure every trigger has an operation.\nforeach (var et in modelBuilder.Model.GetEntityTypes())\nforeach (var t in et.GetTriggers())\n    if (t.GetTriggerOperation() is null)\n        throw new InvalidOperationException($\"Trigger {t.ModelName} on {et.DisplayName()} needs HasTriggerOperation().\");","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Always chain .HasTriggerOperation(...) (Create/Replace/Delete/All) after HasTriggerType(...).","Centralize trigger definitions in one configuration file so both lines stay together.","Add a startup assertion that no trigger has a null operation."],"tags":["cosmos","triggers","model-validation","configuration"],"backgroundTag":null,"analyzedSha":"3a2006ef569de08368d59db5e1468aa8f407e4f8","analyzedAt":"2026-08-11T23:42:04.146Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}