dotnet/wpf · error · ArgumentException

SR.CanOnlyHaveOneChild

Error message

SR.CanOnlyHaveOneChild

What it means

A RichTextBox owns exactly one FlowDocument, created implicitly at construction. Calling IAddChild.AddChild when the implicit document is already in use (i.e. a child was added before, or Document was assigned) throws ArgumentException(SR.CanOnlyHaveOneChild).

Solutions

  1. Provide exactly one FlowDocument child, or set Document once — never both.
  2. Remove the duplicate child or the Document attribute so only one content source remains.
  3. In code, check richTextBox.Document == null before assigning a new document.

Example fix

// before
<RichTextBox><FlowDocument>...</FlowDocument></RichTextBox>
           Document="{Binding Doc}" />
// after
<RichTextBox Document="{Binding Doc}" />
Defensive patterns

Strategy: validation

Validate before calling

if (richTextBox.Document != null)
    richTextBox.Document = newDoc; // replace instead of adding a second child
else
    richTextBox.AddChild(newDoc);

Type guard

bool CanAddChild(RichTextBox rtb) => rtb.Document == null;

Try / catch

try { richTextBox.AddChild(doc); }
catch (ArgumentException ex) when (ex.Message.Contains("one child")) { richTextBox.Document = doc; }

Prevention

When it happens

Trigger: Calling AddChild twice, or mixing XAML child content with an explicit Document property assignment — e.g. <RichTextBox Document="..."><FlowDocument>...</FlowDocument></RichTextBox> or a second AddChild call after content exists.

Common situations: Duplicated content blocks in XAML after template/style expansion; code that both sets .Document and calls AddChild; merge/parse tools emitting the document twice.

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/15f31311e18f735a. Report an issue: GitHub.

Appendix: source

Thrown at src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/Controls/RichTextBox.cs:158

        /// This method is called to Add the object as a child of the RichTextBox.  This method is used primarily
        /// by the parser; a more direct way of adding a child to a RichTextBox is to use the <see cref="Document" />
        /// property.
        ///</summary>
        ///<param name="value">
        /// The object to add as a child; it must be a UIElement.
        ///</param>
        void IAddChild.AddChild(Object value)
        {
            ArgumentNullException.ThrowIfNull(value);

            if (!(value is FlowDocument))
            {
                throw new ArgumentException(SR.Format(SR.UnexpectedParameterType, value.GetType(), typeof(FlowDocument)), nameof(value));
            }

            if (!_implicitDocument)
            {
                throw new ArgumentException(SR.Format(SR.CanOnlyHaveOneChild, this.GetType(), value.GetType()));
            }

            this.Document = (FlowDocument)value;
        }

        ///<summary>
        /// This method is called by the parser when text appears under the tag in markup.
        /// As RichTextBox do not support text, calling this method has no effect if the text
        /// is all whitespace.  For non-whitespace text, throw an exception.
        ///</summary>
        ///<param name="text">
        /// Text to add as a child.
        ///</param> 
        void IAddChild.AddText(string text)
        {
            ArgumentNullException.ThrowIfNull(text);

            XamlSerializerUtil.ThrowIfNonWhiteSpaceInAddText(text, this);

View on GitHub (pinned to 81131a70a4)