dotnet/wpf · error · InvalidOperationException
throw new…
Error message
throw new InvalidOperationException(SR.FrugalList_CannotPromoteBeyondArray);
What it means
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.
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
Example fix
// before
style.Setters.Add(new Setter(...)); // throws CannotPromoteBeyondArray on a corrupted shared style
// after
var style = new Style(typeof(Button)) { BasedOn = sharedStyle };
style.Setters.Add(new Setter(...)); // mutate your own copy Defensive patterns
Strategy: try-catch
Try / catch
try
{
list.Add(value);
}
catch (InvalidOperationException ex) when (ex.Message.Contains("promote"))
{
// corrupt internal store state: recreate the collection and log
list = new FrugalObjectList<T>();
list.Add(value);
} Prevention
- 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
When it happens
Trigger: 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).
Common situations: 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.
Understand the failure class
Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.
Related errors
- Animation_Invalid_DefaultValue
- Cannot remove signature from read-only file.
- Image_EncoderNoColorContext
- Image_EncoderNoGlobalMetadata
- Image_EncoderNoGlobalThumbnail
AI-assisted analysis of dotnet/wpf@81131a70a4 (2026-09-14).
Data as JSON: /api/errors/ea6d9823489109ad.
Report an issue: GitHub.
Appendix: source
Thrown at src/Microsoft.DotNet.Wpf/src/Shared/MS/Utility/FrugalList.cs:1789
// Insert the new item
newStore.Add(value);
_listStore = newStore;
}
else if (myState == FrugalListStoreState.Array)
{
ArrayItemList<T> newStore = new ArrayItemList<T>(_listStore.Count + 1);
// Extract the values from the old store and insert them into the new store
newStore.Promote(_listStore);
_listStore = newStore;
// Insert the new item
newStore.Add(value);
_listStore = newStore;
}
else
{
throw new InvalidOperationException(SR.FrugalList_CannotPromoteBeyondArray);
}
}
return _listStore.Count - 1;
}
public void Clear()
{
_listStore?.Clear();
}
public bool Contains(T value)
{
if ((_listStore is not null) && (_listStore.Count > 0))
{
return _listStore.Contains(value);
}
View on GitHub (pinned to 81131a70a4)