{"record":{"id":"eb969345c0a0f49a","repo":"dotnet/wpf","slug":"sr-propertytriggerlayerlimitexceeded","errorCode":null,"errorMessage":"SR.PropertyTriggerLayerLimitExceeded","messagePattern":"SR\\.PropertyTriggerLayerLimitExceeded","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/TriggerBase.cs","lineNumber":358,"sourceCode":"        //  animation composition.  Otherwise, it stays at default value of zero.\n        internal Int64 Layer\n        {\n            get { return _globalLayerRank; }\n        }\n\n        // Set self rank to current number, increment global static.\n        internal void EstablishLayer()\n        {\n            if( _globalLayerRank == 0 )\n            {\n                lock(Synchronized)\n                {\n                    _globalLayerRank = _nextGlobalLayerRank++;\n                }\n\n                if( _nextGlobalLayerRank == Int64.MaxValue )\n                {\n                    throw new InvalidOperationException(SR.PropertyTriggerLayerLimitExceeded);\n                }\n            }\n        }\n\n        // evaluate the current state of the trigger\n        internal virtual bool GetCurrentState(DependencyObject container, UncommonField<HybridDictionary[]> dataField)\n        {\n            Debug.Assert( false,\n                \"This method was written to handle Trigger, MultiTrigger, DataTrigger, and MultiDataTrigger.  It looks like a new trigger type was added - please add support as appropriate.\");\n\n            return false;\n        }\n\n        // Collection of TriggerConditions\n        internal TriggerCondition[] TriggerConditions\n        {\n            get { return _triggerConditions; }\n            set { _triggerConditions = value; }","sourceCodeStart":340,"sourceCodeEnd":376,"githubUrl":"https://github.com/dotnet/wpf/blob/81131a70a4c573cd62748a5c36908fc4d662daa9/src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/TriggerBase.cs#L340-L376","documentation":"TriggerBase.EstablishLayer assigns each property/data trigger a global layer rank used to order trigger evaluation in styles. WPF throws this InvalidOperationException when the global layer rank counter reaches Int64.MaxValue, meaning an application has created an astronomically large number of trigger layers. This is effectively an internal invariant violation and practically unreachable in normal apps.","triggerScenarios":"Calling Style.Triggers.Add (which routes through AddPropertyTriggerWithAction or AddDataTriggerWithAction) after the process has accumulated Int64.MaxValue trigger layer ranks - only possible with pathological repeated style/trigger instantiation and removal.","commonSituations":"Essentially never seen; would require a long-running process leaking triggers for billions of iterations, or memory corruption affecting _nextGlobalLayerRank.","solutions":["Restart the process; the global layer rank counter cannot be reset","Reduce dynamic style/trigger churn by reusing styles and templates instead of recreating them","Fix any leak where styles or triggers are created in a loop without releasing them","Report to Microsoft if reached without extreme trigger churn, as it indicates counter corruption"],"exampleFix":"// before\nfor (int i = 0; i < int.MaxValue; i++) {\n    var t = new Trigger { Property = UIElement.IsEnabledProperty };\n    var s = new Style { Triggers = { t } }; // churns trigger layers\n}\n// after\nvar sharedTrigger = new Trigger { Property = UIElement.IsEnabledProperty };\nvar sharedStyle = new Style { Triggers = { sharedTrigger } }; // reuse, do not recreate\nfor (int i = 0; i < int.MaxValue; i++) { /* apply sharedStyle */ }","handlingStrategy":"validation","validationCode":"if (style.Triggers.Count > 1000) { throw new InvalidOperationException(\"Excessive trigger churn detected\"); }","typeGuard":null,"tryCatchPattern":"try { style.Triggers.Add(trigger); } catch (InvalidOperationException ex) when (ex.Message.Contains(\"layer\")) { /* log and restart/rebuild styles */ }","preventionTips":["Reuse style/trigger instances instead of recreating them in loops","Pool or cache DynamicResource-driven styles for long-running apps","Avoid unbounded dynamic trigger creation"],"tags":["wpf","triggers","styles","internal-limit"],"backgroundTag":"internal-invariant-violation","analyzedSha":"81131a70a4c573cd62748a5c36908fc4d662daa9","analyzedAt":"2026-09-14T10:12:48.479Z","contentChangedAt":"2026-09-14T10:12:48.479Z","schemaVersion":2},"datasetVersion":"2026-09-22T01:17:13.364Z"}