dotnet/wpf · error · InvalidOperationException

SR.Format(SR.CompatibilityPreferencesSealed…

Error message

SR.Format(SR.CompatibilityPreferencesSealed, "IsVirtualizingStackPanel_45Compatible", "FrameworkCompatibilityPreferences")

What it means

Setting FrameworkCompatibilityPreferences.IsVirtualizingStackPanel_45Compatible after the preferences are sealed throws InvalidOperationException. This switch controls whether VirtualizingStackPanel uses .NET 4.5-compatible behavior; WPF seals it once virtualization code has read the preference so panel behavior cannot change mid-run.

Solutions

  1. Move the assignment to the first line of Main(), before any WPF type is loaded
  2. Guard the assignment with a check of FrameworkCompatibilityPreferences.IsSealed
  3. Remove the runtime toggle and fix the value at build/startup time

Example fix

// before
protected override void OnStartup(StartupEventArgs e)
{
    FrameworkCompatibilityPreferences.IsVirtualizingStackPanel_45Compatible = false; // may already be sealed
}

// after
static void Main()
{
    FrameworkCompatibilityPreferences.IsVirtualizingStackPanel_45Compatible = false;
    var app = new App();
    app.Run();
}
Defensive patterns

Strategy: validation

Validate before calling

if (!FrameworkCompatibilityPreferences.IsSealed)
    FrameworkCompatibilityPreferences.IsVirtualizingStackPanel_45Compatible = false;

Type guard

bool PrefsWritable => !FrameworkCompatibilityPreferences.IsSealed;

Try / catch

try { FrameworkCompatibilityPreferences.IsVirtualizingStackPanel_45Compatible = v; }
catch (InvalidOperationException ex) { log.Warn(ex); }

Prevention

When it happens

Trigger: Assigning the static IsVirtualizingStackPanel_45Compatible property after WPF has been initialized (first list/virtualization usage, Dispatcher started, or IsSealed == true).

Common situations: Setting the switch in a page/window constructor, or attempting to change virtualization behavior after the app has rendered its first VirtualizingStackPanel-based list.

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

Appendix: source

Thrown at src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/FrameworkCompatibilityPreferences.cs:244

        // The 4.5 algorithm had many flaws, leading to infinite loops, scrolling
        // to the wrong place, and other bad symptoms.  DDCC is worried that fixing
        // these issues may introduce new compat problems, and asked for a way to opt out
        // of the fixes.  To opt out, add an entry to the <appSettings> section of the
        // app config file:
        //          <add key="IsVirtualizingStackPanel_45Compatible" value="true"/>

        private static bool _vsp45Compat = false;

        internal static bool VSP45Compat
        {
            get { return _vsp45Compat; }
            set
            {
                lock (_lockObject)
                {
                    if (_isSealed)
                    {
                        throw new InvalidOperationException(SR.Format(SR.CompatibilityPreferencesSealed, "IsVirtualizingStackPanel_45Compatible", "FrameworkCompatibilityPreferences"));
                    }

                    _vsp45Compat = value;
                }
            }
        }

        internal static bool GetVSP45Compat()
        {
            Seal();

            return VSP45Compat;
        }

        private static void SetVSP45CompatFromAppSettings(NameValueCollection appSettings)
        {
            // user can use config file to opt out of VSP fixes
            string s = appSettings["IsVirtualizingStackPanel_45Compatible"];

View on GitHub (pinned to 81131a70a4)