dotnet/wpf · error · InvalidOperationException
SR.Format(SR.AlreadyHasLogicalChildren…
Error message
SR.Format(SR.AlreadyHasLogicalChildren, parent.GetType().Name)
What it means
AddNodeToLogicalTree, when the parent is a FrameworkContentElement, checks whether that parent already has logical children. Factory-built content is meant to become the sole logical child in this path; if the instantiated parent already enumerates at least one logical child, the framework throws InvalidOperationException(AlreadyHasLogicalChildren) naming the parent type, because it cannot unambiguously attach the factory node.
Solutions
- Clear the parent's existing content/children before applying the factory-built tree.
- Use a fresh, empty parent instance for the template instantiation.
- Restructure so the factory node is added through the parent's collection API rather than the single-logical-child path.
Example fix
// before paragraph.Inlines.Add(existingRun); template.LoadContent(); // factory node attach fails // after var freshParagraph = new Paragraph(); // empty parent for factory content
Defensive patterns
Strategy: validation
Validate before calling
if (parent is FrameworkContentElement fce && fce.LogicalChildren != null && fce.LogicalChildren.MoveNext())
throw new InvalidOperationException($"{fce.GetType().Name} already has logical children; use an empty parent"); Type guard
bool IsEmptyLogicalParent(FrameworkContentElement e) { var it = e.LogicalChildren; return it == null || !it.MoveNext(); } Try / catch
try { template.LoadContent(); } catch (InvalidOperationException ex) when (ex.Message.Contains("logical children")) { /* clear content or create fresh parent */ } Prevention
- Instantiate factory trees into fresh, empty parent instances
- Clear Content/Children before re-applying a template
- Do not reuse populated FrameworkContentElements as template roots
When it happens
Trigger: Instantiating a factory tree where a FrameworkContentElement node (e.g. a Paragraph or another content element) already has children — for example a control whose content was set earlier — and AddNodeToLogicalTree then attempts to attach the factory-built node.
Common situations: Reusing a pre-populated control instance as a template root; template content applied over an element whose Content/Children were already populated by prior code; FlowDocument content elements with existing inlines used inside generated templates.
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
- ' ' must be the root element of a tree, but has a logical…
- Decorator marked as PART_ContentHost must have no content.
- InvalidOperationException (no message)
- Only Decorator and ScrollViewer can be used as…
- ScrollViewer marked as PART_ContentHost must have no…
AI-assisted analysis of dotnet/wpf@81131a70a4 (2026-09-14).
Data as JSON: /api/errors/af63bc761870a452.
Report an issue: GitHub.
Appendix: source
Thrown at src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/FrameworkElementFactory.cs:1111
/// it is actually added to the logical tree because FrameworkContentElement
/// has no visual tree.
/// </summary>
/// <remarks>
/// A prime example of trying to shove a square peg into a round hole.
/// </remarks>
internal static void AddNodeToLogicalTree( DependencyObject parent, Type type,
bool treeNodeIsFE, FrameworkElement treeNodeFE, FrameworkContentElement treeNodeFCE)
{
// If the logical parent already has children, then we can't add
// a logical subtree from the style, since there would be a conflict.
// Throw an exception in this case.
FrameworkContentElement logicalParent = parent as FrameworkContentElement;
if (logicalParent != null)
{
IEnumerator childEnumerator = logicalParent.LogicalChildren;
if (childEnumerator != null && childEnumerator.MoveNext())
{
throw new InvalidOperationException(SR.Format(SR.AlreadyHasLogicalChildren,
parent.GetType().Name));
}
}
IAddChild addChildParent = parent as IAddChild;
if (addChildParent == null)
{
throw new InvalidOperationException(SR.Format(SR.CannotHookupFCERoot,
type.Name));
}
else
{
if (treeNodeFE != null)
{
addChildParent.AddChild(treeNodeFE);
}
else
{View on GitHub (pinned to 81131a70a4)