dotnet/wpf · error · InvalidOperationException

SR.ParserCanOnlyHaveOneChild

Error message

SR.ParserCanOnlyHaveOneChild

What it means

InvalidOperationException with SR.ParserCanOnlyHaveOneChild raised by XamlReaderHelper when a XAML element or property element that may only contain a single child element receives a second one. The parser stops because the parent's type/property cannot accept more than one child object.

Solutions

  1. Remove the extra child element or wrap multiple children in a container (Grid, StackPanel, etc.).
  2. Move one child into a property element (e.g. <Button.Content>, <Button.ToolTip>) if intended.
  3. If the parent should hold many children, change the parent type to a collection type or ensure the target property is a list/dictionary.
  4. Check the parent and child type names in the error message to identify exactly which pair conflicts.

Example fix

// before
<Button><Grid/><Button.Content>X</Button.Content></Button>
// after
<Button><Grid/></Button>
Defensive patterns

Strategy: validation

Validate before calling

// for a scalar Content property, ensure exactly one child
int childCount = parentElement.Elements().Count();
if (childCount > 1) throw new InvalidOperationException($"{parent.Name} accepts only one child but has {childCount}");

Type guard

static bool AllowsMultipleChildren(Type t) => typeof(System.Collections.IEnumerable).IsAssignableFrom(t) && t != typeof(string);

Try / catch

try { var obj = (T)XamlReader.Parse(xaml); } catch (InvalidOperationException ex) when (ex.Message.Contains("one child")) { log.Error(ex.Message); throw new XamlContentModelException(ex); }

Prevention

When it happens

Trigger: Parsing XAML where two element children appear under a parent (parent tag or property element) whose type is not a collection/content container; raised while processing the second ObjectElement in ReadElementStart flow.

Common situations: Declaring two children on a control with a single Content property (e.g. two elements inside <Button> or two elements inside a non-collection property element like <Window.Title>).

Understand the failure class

Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.

Related errors


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

Appendix: source

Thrown at src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/Markup/XamlReaderHelper.cs:4354

                // returns false if there are multiple elements but
                // the property is not a container.
                if (!VerifyContentPropertySeesAnElement(ParentContext))
                {
                    //We need to error, do work to give a good error message.
                    string FirstTagName;

                    if (ParentContext.ContextDataType == null)
                    {
                        //PropertyElement was the Parent tag.
                        FirstTagName = $"{((Type)GrandParentContext.ContextData).Name}.{GrandParentContext.ChildTagLocalName}";
                    }
                    else
                    {
                        //ObjectElement was the Parent tag.
                        FirstTagName = ParentContext.ContextDataType.Name;
                    }

                    throw new InvalidOperationException(SR.Format(SR.ParserCanOnlyHaveOneChild,
                        FirstTagName /* Parent or PropertyElement*/,
                        CurrentContext.ContextDataType.Name /* Child */));
                }
            }

            // If we previously synthesised an ElementStart and we now really have
            // a true element tag as the first child tag, then remove the previously synthesised node from
            // the reader's node collection, and mark the current context as not
            // needing to synthesis an end tag.
            // NOTE: We will only remove the synthesised node if it is a match for
            //       for the one specified in the actual XAML.  We consider it a match
            //       for the property class if it is a subclass of the property type
            if (ParentContext != null &&
                ParentContext.ContextData != null &&
                ParentContext.NeedToWriteEndElement &&
                !ParentContext.FirstChildRead)
            {

View on GitHub (pinned to 81131a70a4)