dotnet/wpf · error · InvalidOperationException
SR.ParserCompatDuplicate formatted with (oldXmlns…
Error message
SR.ParserCompatDuplicate formatted with (oldXmlns, newXmlns) - duplicate XmlnsCompatibleWithAttribute mapping for the same old namespace
What it means
XmlnsCache throws InvalidOperationException when two XmlnsCompatibleWithAttribute declarations map the same OldNamespace to different NewNamespace values. The compatibility table (_compatTable) can hold only one new-namespace mapping per old namespace, so a conflicting second mapping is ambiguous and rejected.
Solutions
- Find all XmlnsCompatibleWithAttribute declarations whose OldNamespace matches the oldXmlns in the message and remove or correct the conflicting one
- Ensure only one NewNamespace is declared per OldNamespace across all referenced assemblies
- Remove stale compatibility shims from older library versions still referenced by the project
- If both mappings are needed for different scenarios, split the assemblies so both are never loaded together in the same XAML compilation
Example fix
// before
[assembly: XmlnsCompatibleWith("clr-namespace:Lib.V1", "clr-namespace:Lib.V2")]
[assembly: XmlnsCompatibleWith("clr-namespace:Lib.V1", "clr-namespace:Lib.V3")] // conflict
// after
[assembly: XmlnsCompatibleWith("clr-namespace:Lib.V1", "clr-namespace:Lib.V3")] Defensive patterns
Strategy: validation
Validate before calling
var seen = new Dictionary<string,string>();
foreach (var a in assemblies.SelectMany(a => a.GetCustomAttributes<XmlnsCompatibleWithAttribute>()))
{
if (seen.TryGetValue(a.OldNamespace, out var prev) && prev != a.NewNamespace)
throw new InvalidOperationException($"Conflicting XmlnsCompatibleWith mapping for {a.OldNamespace}");
seen[a.OldNamespace] = a.NewNamespace;
} Prevention
- Declare exactly one XmlnsCompatibleWithAttribute per old namespace across all referenced assemblies
- Remove compatibility shims from old library versions when upgrading
- Document namespace migrations to avoid parallel conflicting mappings
When it happens
Trigger: Calling AddReferencedAssemblies or GetMappingArray while scanning assemblies containing e.g. [assembly: XmlnsCompatibleWith("old-ns", "ns-A")] in one assembly and [assembly: XmlnsCompatibleWith("old-ns", "ns-B")] in another (or the same) assembly.
Common situations: Referencing two versions of a control library that each declare a different compatibility target for the same old namespace; a library rename where an old compatibility shim was left alongside the new mapping.
Understand the failure class
Background: Conflicting config options: "cannot be used together" — configuration validation errors across open-source libraries — this error's family across 162 libraries.
Related errors
- message (InvalidOperationException)
- SR.DuplicateXmlnsCompatAcrossAssemblies
- SR.ParserAttributeArgsLow with…
- Animation_ChildMustBeKeyFrame
- Animation_ChildMustBeKeyFrame
AI-assisted analysis of dotnet/wpf@81131a70a4 (2026-09-14).
Data as JSON: /api/errors/00c170341cdc5013.
Report an issue: GitHub.
Appendix: source
Thrown at src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/Markup/XmlnsCache.cs:393
typeof(XmlnsCompatibleWithAttribute));
#endif
for(int attrIdx=0; attrIdx<attributes.Length; attrIdx++)
{
string oldXmlns = null;
string newXmlns = null;
GetNamespacesFromCompatAttr(attributes[attrIdx], out oldXmlns, out newXmlns);
if (String.IsNullOrEmpty(oldXmlns) || String.IsNullOrEmpty(newXmlns))
{
throw new ArgumentException(SR.Format(SR.ParserAttributeArgsLow, "XmlnsCompatibleWithAttribute"));
}
if (_compatTable.ContainsKey(oldXmlns) &&
_compatTable[oldXmlns] != newXmlns)
{
throw new InvalidOperationException(SR.Format(SR.ParserCompatDuplicate, oldXmlns,
_compatTable[oldXmlns]));
}
_compatTable[oldXmlns] = newXmlns;
_compatTableReverse[newXmlns] = oldXmlns;
}
}
}
// Table where Xml namespace is the key, and value is a list of assembly / clrns pairs
private HybridDictionary _cacheTable = null;
// Table where old namespaces are the key, and new namespaces are the value
private Dictionary<string, string> _compatTable = null;
// Table where new namespaces are the key, and old namespaces are the value
private Dictionary<string, string> _compatTableReverse = null;
#if !PBTCOMPILERView on GitHub (pinned to 81131a70a4)