dotnet/wpf · error · XamlSchemaException

SR.XmlnsCompatCycle

Error message

SR.XmlnsCompatCycle

What it means

System.Xaml throws XamlSchemaException(SR.XmlnsCompatCycle) when the old-to-new namespace mapping defined by XmlnsCompat attributes contains a cycle (e.g. nsA -> nsB -> nsA). NamespaceComparer walks the chain to compute transitive subsumption counts and detects a repeated namespace via the visited set.

Solutions

  1. Break the cycle by removing or correcting one XmlnsCompat mapping so the chain is acyclic and ends at the current namespace.
  2. Keep only mappings that point strictly from older to newer namespaces, one direction only.
  3. Audit all assemblies' XmlnsCompat attributes after namespace migrations for conflicting directions.

Example fix

// before (cycle)
[assembly: XmlnsCompat("clr-namespace:A", "clr-namespace:B")]
[assembly: XmlnsCompat("clr-namespace:B", "clr-namespace:A")]
// after (acyclic)
[assembly: XmlnsCompat("clr-namespace:A", "clr-namespace:B")]
Defensive patterns

Strategy: validation

Validate before calling

var map = new Dictionary<string,string> { ["clr-namespace:A"]="clr-namespace:B" }; var seen = new HashSet<string>(); var ns = startNs; while (ns != null && map.ContainsKey(ns)) { if (!seen.Add(ns)) throw new InvalidOperationException("XmlnsCompat cycle at " + ns); ns = map[ns]; }

Try / catch

try { loadXaml(); } catch (XamlSchemaException ex) when (ex.Message.Contains("XmlnsCompatCycle")) { /* remove the cyclic mapping */ }

Prevention

When it happens

Trigger: Assembly-level XmlnsCompat attributes form a loop such that GetNewNs(ns) eventually returns a namespace already visited; encountered in NamespaceComparer while ordering namespaces.

Common situations: Namespace refactors done in both directions (A->B and B->A attributes kept simultaneously), merged assembly attributes from different branches each mapping the namespaces toward their own version.

Understand the failure class

Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.

Related errors


AI-assisted analysis of dotnet/wpf@81131a70a4 (2026-09-14). Data as JSON: /api/errors/984c661afba554c5. Report an issue: GitHub.

Appendix: source

Thrown at src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/MS/Impl/XmlNsInfo.cs:473

                _nsInfo = nsInfo;

                // Calculate the subsume count upfront, since this also serves as our cycle detection
                _subsumeCount = new Dictionary<string, int>(nsInfo.OldToNewNs.Count);

                HashSet<string> visited = new HashSet<string>();

                // for every XmlnsCompatAttribute
                foreach (string newNs in nsInfo.OldToNewNs.Values)
                {
                    visited.Clear();

                    // Increment the subsume count for all transitive subsumers
                    string ns = newNs;
                    do
                    {
                        if (!visited.Add(ns))
                        {
                            throw new XamlSchemaException(SR.Format(SR.XmlnsCompatCycle, assembly.FullName, ns));
                        }

                        IncrementSubsumeCount(ns);
                        ns = GetNewNs(ns);
                    }
                    while (ns is not null);
                }
            }

            public int CompareNamespacesByPreference(string ns1, string ns2)
            {
                if (KS.Eq(ns1, ns2))
                {
                    return 0;
                }

                const int Prefer_NS1 = -1;
                const int Prefer_NS2 = 1;

View on GitHub (pinned to 81131a70a4)