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
- Provide exactly one FlowDocument child, or set Document once — never both.
- Remove the duplicate child or the Document attribute so only one content source remains.
- 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
- Provide exactly one content source: either a single XAML child or a Document assignment.
- Audit XAML merge tools/styles for duplicated RichTextBox content.
- In helpers, always route through the Document property, never AddChild.
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
- SR.UnexpectedParameterType
- SR.CanOnlyHaveOneChild
- SR.Format(SR.ParserPrefixNSProperty, nsPrefix, nameString)
- SR.NameScopeNameNotFound
- SR.ParserAttributeArgsLow
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)