{"record":{"id":"ea6d9823489109ad","repo":"dotnet/wpf","slug":"throw-new-invalidoperationexception-sr-frugallist","errorCode":null,"errorMessage":"throw new InvalidOperationException(SR.FrugalList_CannotPromoteBeyondArray);","messagePattern":"throw new InvalidOperationException\\(SR\\.FrugalList_CannotPromoteBeyondArray\\);","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"src/Microsoft.DotNet.Wpf/src/Shared/MS/Utility/FrugalList.cs","lineNumber":1789,"sourceCode":"                    // Insert the new item\n                    newStore.Add(value);\n                    _listStore = newStore;\n                }\n                else if (myState == FrugalListStoreState.Array)\n                {\n                    ArrayItemList<T> newStore = new ArrayItemList<T>(_listStore.Count + 1);\n\n                    // Extract the values from the old store and insert them into the new store\n                    newStore.Promote(_listStore);\n                    _listStore = newStore;\n\n                    // Insert the new item\n                    newStore.Add(value);\n                    _listStore = newStore;\n                }\n                else\n                {\n                    throw new InvalidOperationException(SR.FrugalList_CannotPromoteBeyondArray);\n                }\n            }\n\n            return _listStore.Count - 1;\n        }\n\n        public void Clear()\n        {\n            _listStore?.Clear();\n        }\n\n        public bool Contains(T value)\n        {\n            if ((_listStore is not null) && (_listStore.Count > 0))\n            {\n                return _listStore.Contains(value);\n            }\n","sourceCodeStart":1771,"sourceCodeEnd":1807,"githubUrl":"https://github.com/dotnet/wpf/blob/81131a70a4c573cd62748a5c36908fc4d662daa9/src/Microsoft.DotNet.Wpf/src/Shared/MS/Utility/FrugalList.cs#L1771-L1807","documentation":"FrugalObjectList<T>.Add hit an internal storage-promotion state it cannot handle. The frugal list stores items in escalating containers (1 item, 3 items, 6 items, then a growable array); if Add returns a store state beyond Array there is no larger container to promote into, so the library throws InvalidOperationException(FrugalList_CannotPromoteBeyondArray). This is effectively an internal invariant violation of the storage model, not something caller input normally causes.","triggerScenarios":"Calling Add on a FrugalObjectList<T> when the internal store's Add returns a FrugalListStoreState other than Success/ThreeItemList/SixItemList/Array (e.g. an unexpected or corrupted store state).","commonSituations":"Practically only seen inside WPF itself or when reflection/custom code has mutated the private _listStore; typical WPF property-system operations (styles, triggers, resource dictionaries) filling shared lists.","solutions":["Report as a WPF bug if hit from normal API use (dotnet/wpf repo) — caller code cannot fix the store state","Update to the latest .NET/WPF servicing release, as frugal-collection bugs have been fixed over time","Stop mutating shared WPF objects (e.g. a Style or ResourceDictionary) from multiple threads; concurrent mutation can corrupt list state","As a workaround, replace the shared container with a fresh instance rather than continuing to Add into the failing one"],"exampleFix":"// before\nstyle.Setters.Add(new Setter(...)); // throws CannotPromoteBeyondArray on a corrupted shared style\n// after\nvar style = new Style(typeof(Button)) { BasedOn = sharedStyle };\nstyle.Setters.Add(new Setter(...)); // mutate your own copy","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try\n{\n    list.Add(value);\n}\ncatch (InvalidOperationException ex) when (ex.Message.Contains(\"promote\"))\n{\n    // corrupt internal store state: recreate the collection and log\n    list = new FrugalObjectList<T>();\n    list.Add(value);\n}","preventionTips":["Do not mutate WPF shared objects (styles, resources, metadata) from multiple threads","Treat FrugalObjectList internals as opaque — never touch _listStore via reflection","Keep .NET/WPF runtime patched","Recreate collections instead of continuing after unexpected collection exceptions"],"tags":["wpf","frugal-list","invalid-operation","internal-state"],"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-21T21:30:21.729Z"}