dotnet/wpf · error · InvalidOperationException

SR.Format(SR.CannotChangeAfterSealed, "SetterBase")

Error message

SR.Format(SR.CannotChangeAfterSealed, "SetterBase")

What it means

SetterBase.CheckSealed throws InvalidOperationException once the setter's owning style/template has been sealed (made immutable after first use). This is WPF's immutability guard: sealed style objects cannot be modified, so any mutation after sealing fails with 'CannotChangeAfterSealed'.

Solutions

  1. Create a new Style/Setter instance (possibly BasedOn the original) instead of mutating the sealed one.
  2. If a style must be modified before use, do all mutations before applying it to any element.
  3. For shared mutable styles, keep an unsealed master copy and generate fresh styles per modification.

Example fix

// before
var style = (Style)button.FindResource(typeof(Button));
style.Setters[0].Value = Brushes.Green; // sealed
// after
var newStyle = new Style(typeof(Button), style);
newStyle.Setters.Add(new Setter(Control.BackgroundProperty, Brushes.Green));
button.Style = newStyle;
Defensive patterns

Strategy: try-catch

Validate before calling

if (setter.IsSealed) throw new InvalidOperationException("Create a new Setter instead of mutating");

Try / catch

try { setter.Value = newValue; }
catch (InvalidOperationException ex) when (ex.Message.Contains("CannotChangeAfterSealed")) { /* rebuild style */ }

Prevention

When it happens

Trigger: Modifying a Setter (Property or Value) after its style has been applied to an element or the style was sealed via style.Seal(); e.g. `setter.Value = x` on a setter retrieved from an applied style.

Common situations: Caching Style instances and mutating them later; tweaking a shared theme style at runtime; iterating Styles from FindResource and editing them.

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/d2366bd8fd0aa55c. Report an issue: GitHub.

Appendix: source

Thrown at src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/SetterBase.cs:50

            get
            {
                return _sealed;
            }
        }

        internal virtual void Seal()
        {
            _sealed = true;
        }

        /// <summary>
        ///  Subclasses need to call this method before any changes to their state.
        /// </summary>
        protected void CheckSealed()
        {
            if ( _sealed )
            {
                throw new InvalidOperationException(SR.Format(SR.CannotChangeAfterSealed, "SetterBase"));
            }            
        }

        // Derived
        private bool _sealed;
    }
        
}

View on GitHub (pinned to 81131a70a4)