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

  1. Build a new Style (with BasedOn) with the desired setters and assign it to the element.
  2. Perform all collection edits before the style is first applied/sealed.
  3. 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

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


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)