{"record":{"id":"0a84dfd24c4e437f","repo":"dotnet/wpf","slug":"sr-triggeractionalreadysealed","errorCode":null,"errorMessage":"SR.TriggerActionAlreadySealed","messagePattern":"SR\\.TriggerActionAlreadySealed","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/TriggerAction.cs","lineNumber":102,"sourceCode":"        {\n            if( IsSealed && containingTrigger != _containingTrigger )\n            {\n                throw new InvalidOperationException(SR.TriggerActionMustBelongToASingleTrigger);\n            }\n            _containingTrigger = containingTrigger;\n            Seal();\n        }\n\n        /// <summary>\n        ///     A derived class overrideing Seal() should set object state such\n        /// that further changes are not allowed.  This is also a time to make\n        /// validation checks to see if all parameters make sense.\n        /// </summary>\n        internal override void Seal()\n        {\n            if( IsSealed )\n            {\n                throw new InvalidOperationException(SR.TriggerActionAlreadySealed);\n            }\n            base.Seal();\n        }\n\n        /// <summary>\n        ///     Checks sealed status and throws exception if object is sealed\n        /// </summary>\n        internal void CheckSealed()\n        {\n            if( IsSealed )\n            {\n                throw new InvalidOperationException(SR.Format(SR.CannotChangeAfterSealed, \"TriggerAction\"));\n            }\n        }\n\n        // Define the DO's inheritance context\n\n        internal override DependencyObject InheritanceContext","sourceCodeStart":84,"sourceCodeEnd":120,"githubUrl":"https://github.com/dotnet/wpf/blob/81131a70a4c573cd62748a5c36908fc4d662daa9/src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/TriggerAction.cs#L84-L120","documentation":"TriggerAction.Seal() throws InvalidOperationException with SR.TriggerActionAlreadySealed when Seal() is invoked on a TriggerAction that is already sealed. WPF seals triggers/actions when the owning Style or Template is sealed (made immutable), typically when it is first used by an element. The check is an internal invariant guard against double-sealing.","triggerScenarios":"Calling the internal Seal() method on a TriggerAction instance whose IsSealed is already true — i.e., sealing the same action twice, usually via two Seal() passes over the same style/template graph.","commonSituations":"Reusing one shared TriggerAction/Style object across multiple styles or templates that each trigger sealing; custom framework code that calls Seal() manually on a style already in use.","solutions":["Do not call Seal() explicitly on styles/triggers; let WPF seal them when the style is applied","If reusing trigger objects, create a new TriggerAction instance per Style instead of sharing one","Check IsSealed before any manual Seal()/mutation and skip or clone if already sealed"],"exampleFix":"// before\nif (!myAction.IsSealed) { /* mutate */ }\nmyAction.Seal(); // may already be sealed\n// after\nif (myAction.IsSealed)\n{\n    myAction = (TriggerAction)CloneCurrentValue(); // work on a fresh copy\n}\nelse { /* mutate */ myAction.Seal(); }","handlingStrategy":"validation","validationCode":"if (!action.IsSealed) { action.Seal(); }","typeGuard":"static bool CanSeal(TriggerAction a) => a != null && !a.IsSealed;","tryCatchPattern":null,"preventionTips":["Never call Seal() manually; let WPF seal styles on application","Don't share TriggerAction instances across styles","Check IsSealed before any manual lifecycle calls"],"tags":["wpf","styles","sealed-object","invalid-operation"],"backgroundTag":"invalid-state-transition","analyzedSha":"81131a70a4c573cd62748a5c36908fc4d662daa9","analyzedAt":"2026-09-14T10:12:48.479Z","contentChangedAt":"2026-09-14T10:12:48.479Z","schemaVersion":2},"datasetVersion":"2026-09-21T21:30:21.729Z"}