dotnet/wpf · error · InvalidOperationException

SR.ParserDictionarySealed (the dictionary is sealed and…

Error message

SR.ParserDictionarySealed (the dictionary is sealed and cannot be modified)

What it means

XmlnsDictionary.CheckSealed throws InvalidOperationException when the dictionary is read-only (sealed, typically because its owning ParserContext has been frozen after parsing). Sealed dictionaries may no longer be mutated: Clear, PushScope, PopScope, AddNamespace, and RemoveNamespace all funnel through this check.

Solutions

  1. Create a new ParserContext / XmlnsDictionary for each parse instead of mutating a sealed one
  2. Clone the sealed dictionary via the copy constructor new XmlnsDictionary(sealedDict) — the copy is mutable — then modify the copy
  3. Check IsReadOnly before mutating and take the copy path when true

Example fix

// before
cachedContext.XmlnsDictionary.AddNamespace("x", "http://example.com/x"); // throws if sealed

// after
var dict = cachedContext.XmlnsDictionary.IsReadOnly
    ? new XmlnsDictionary(cachedContext.XmlnsDictionary)
    : cachedContext.XmlnsDictionary;
dict.AddNamespace("x", "http://example.com/x");
Defensive patterns

Strategy: validation

Validate before calling

if (dict.IsReadOnly)
    dict = new XmlnsDictionary(dict); // mutable copy
else
    dict.PushScope();

Type guard

bool IsMutable(XmlnsDictionary d) => !d.IsReadOnly;

Try / catch

try { dict.AddNamespace("x", nsUri); }
catch (InvalidOperationException) { dict = new XmlnsDictionary(dict); dict.AddNamespace("x", nsUri); }

Prevention

When it happens

Trigger: Calling Clear, PushScope, PopScope, AddNamespace, RemoveNamespace, Add, or the indexer setter on an XmlnsDictionary whose IsReadOnly is true (e.g. ParserContext.XmlnsDictionary of a context that finished parsing or was sealed).

Common situations: Reusing a cached ParserContext across multiple XAML parse operations and trying to register new namespaces on it; mutating a dictionary captured from a completed parse session.

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

Appendix: source

Thrown at src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/Markup/XmlnsDictionary.cs:594

#region Private       
        private void Initialize()
        {
            // We set the initial array to 8 and double from there when we run of the space. 
            // For the start case, we set the DefaultNamespaceuri to null. 
            _nsDeclarations = new NamespaceDeclaration[8];
            _nsDeclarations[0].Prefix = string.Empty;
            _nsDeclarations[0].Uri = null;
            _nsDeclarations[0].ScopeCount = 0;
            _lastDecl = 0;
            _countDecl = 0;
       }

       private void CheckSealed()
        {
            if (IsReadOnly)
            {
                throw new InvalidOperationException(SR.ParserDictionarySealed);
            }
        }

        /// <summary>
        /// Helper to Add Namespace - Checks for prefix from rear.
        ///  If exists : override it locally, if not Adds an entry.
        /// </summary>
        /// <param name="prefix">prefix to add</param>
        /// <param name="xmlNamespace">namespace uri string to add</param>
        private void AddNamespace(string prefix, string xmlNamespace)
        {
            CheckSealed();
            
            if (xmlNamespace == null)
                throw new ArgumentNullException(nameof(xmlNamespace));

            if (prefix == null)
                throw new ArgumentNullException(nameof(prefix));

View on GitHub (pinned to 81131a70a4)