dotnet/wpf · error · InvalidOperationException
SR.Format(SR.CannotChangeAfterSealed…
Error message
SR.Format(SR.CannotChangeAfterSealed, "SetterBaseCollection")
What it means
SetterBaseCollection.CheckSealed throws InvalidOperationException when the collection is sealed (its owning style/template is in use). ClearItems, InsertItem, RemoveItem and SetItem all call it, so any add/remove/replace/clear on a sealed setter collection throws 'CannotChangeAfterSealed: SetterBaseCollection'.
Solutions
- Build a new Style (with BasedOn) with the desired setters and assign it to the element.
- Perform all collection edits before the style is first applied/sealed.
- If the style came from a resource dictionary, replace the dictionary entry with a new Style instance.
Example fix
// before style.Setters.Clear(); // style already in use // after var newStyle = new Style(style.TargetType, style); newStyle.Setters.Add(new Setter(Control.BackgroundProperty, Brushes.Yellow)); button.Style = newStyle;
Defensive patterns
Strategy: try-catch
Validate before calling
if (style.IsSealed) { /* clone: new Style(style.TargetType, style) before edits */ } Try / catch
try { style.Setters.Add(newSetter); }
catch (InvalidOperationException ex) when (ex.Message.Contains("SetterBaseCollection")) { /* build and assign a new Style */ } Prevention
- Never mutate Setters collections of styles in use; clone via BasedOn
- Complete all collection edits before first application of the style
When it happens
Trigger: Calling style.Setters.Add/Remove/Clear on a style after it was applied to an element or explicitly sealed; shared resource-dictionary styles mutated at runtime.
Common situations: Hot-swapping setters in an in-use style; plugin code editing application-wide theme styles; tests reusing a cached Style object across assertions.
Understand the failure class
Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.
Related errors
- SR.CannotChangeAfterSealed
- SR.Format(SR.CannotChangeAfterSealed, "SetterBase")
- SR.Format(SR.CannotChangeAfterSealed, "Style")
- SR.Format(SR.CannotChangeAfterSealed, "TriggerCollection")
- Cannot pass multidimensional array to the CopyTo method on…
AI-assisted analysis of dotnet/wpf@81131a70a4 (2026-09-14).
Data as JSON: /api/errors/22e0107eb0a88289.
Report an issue: GitHub.
Appendix: source
Thrown at src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/SetterBaseCollection.cs:101
{
_sealed = true;
// Seal all the setters
for (int i=0; i<Count; i++)
{
this[i].Seal();
}
}
#endregion InternalMethods
#region PrivateMethods
private void CheckSealed()
{
if (_sealed)
{
throw new InvalidOperationException(SR.Format(SR.CannotChangeAfterSealed, "SetterBaseCollection"));
}
}
private void SetterBaseValidation(SetterBase setterBase)
{
ArgumentNullException.ThrowIfNull(setterBase);
}
#endregion PrivateMethods
#region Data
private bool _sealed;
#endregion Data
}
}
View on GitHub (pinned to 81131a70a4)