dotnet/wpf · error · XamlObjectReaderException

SR.ObjectReaderXamlNamedElementAlreadyRegistered

Error message

SR.ObjectReaderXamlNamedElementAlreadyRegistered

What it means

XamlObjectReader throws this when two elements in the same XAML namescope carry the same x:Name (or Name). XAML names must be unique within a namescope, so duplicate names make the round-tripped markup ambiguous and namescope resolution impossible.

Solutions

  1. Assign unique names within each namescope before constructing the reader
  2. Clear the Name property on duplicates if the name is not needed
  3. Put conflicting subtrees into separate XamlNamescope-equivalent containers
  4. Generate names programmatically (e.g. with a counter) when cloning trees

Example fix

// before (in a clone loop)
clone.Name = original.Name;
// after
clone.Name = original.Name + "_" + index;
Defensive patterns

Strategy: validation

Validate before calling

var seen = new HashSet<string>(StringComparer.Ordinal);
void Walk(DependencyObject o) { var n = o is FrameworkElement fe ? fe.Name : null; if (!string.IsNullOrEmpty(n) && !seen.Add(n)) throw new InvalidOperationException($"Duplicate name: {n}"); foreach (object c in LogicalTreeHelper.GetChildren(o).OfType<DependencyObject>()) Walk(c); }

Try / catch

try { using var r = new XamlObjectReader(obj); ... } catch (XamlObjectReaderException ex) when (ex.Message.Contains("AlreadyRegistered")) { /* deduplicate names */ }

Prevention

When it happens

Trigger: new XamlObjectReader(obj) on a graph (e.g. WPF element tree or object tree with Name properties set) where EnsureNoDuplicateNames finds the same Name string twice within one namescope.

Common situations: Programmatic UI construction that assigns the same Name in a loop; cloning/copying element trees without renaming; deserializing trees that were merged from two documents with colliding names.

Related errors


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

Appendix: source

Thrown at src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/XamlObjectReader.cs:1781

                });

                // some collection or dictionary's object node might have been removed
                // i.e. XamlNode is now changed to GetObject.  since we are now naming
                // the object, we need to add the object node back
                if (XamlNode.NodeType == XamlNodeType.GetObject)
                {
                    Debug.Assert(Object is not null);
                    var xamlType = context.LocalAssemblyAwareGetXamlType(Object.GetType());
                    XamlNode = new XamlNode(XamlNodeType.StartObject, xamlType);
                }
            }

            public override void EnsureNoDuplicateNames(Stack<HashSet<string>> namesInCurrentScope)
            {
                if (!string.IsNullOrEmpty(Name) &&
                    !namesInCurrentScope.Peek().Add(Name))
                {
                    throw new XamlObjectReaderException(SR.Format(SR.ObjectReaderXamlNamedElementAlreadyRegistered, Name));
                }

                // Recurse through all of the values I have.
                foreach (var property in Properties)
                {
                    var propertyInfo = (MemberMarkupInfo)property;
                    foreach (var ov in propertyInfo.Children)
                    {
                        ((ObjectOrValueMarkupInfo)ov).EnsureNoDuplicateNames(namesInCurrentScope);
                    }
                }
            }

            private static string ConvertTypeAndMethodToString(Type type, string methodName, SerializerContext context)
            {
                string typestring = context.ConvertXamlTypeToString(context.LocalAssemblyAwareGetXamlType(type));

                return $"{typestring}.{methodName}";

View on GitHub (pinned to 81131a70a4)