dotnet/wpf · error · InvalidOperationException
SR.Format(SR.CannotHookupFCERoot, type.Name)
Error message
SR.Format(SR.CannotHookupFCERoot, type.Name)
What it means
AddNodeToLogicalTree requires a way to attach the factory-built node to its parent. When the parent is not a FrameworkElement, not a FrameworkContentElement with valid handling, and does not implement IAddChild, there is no available hookup mechanism for the FCE root, so the framework throws InvalidOperationException(CannotHookupFCERoot) naming the type. Essentially the parent type lacks any supported child-attachment contract.
Solutions
- Use a supported root type: FrameworkElement (Panel, ContentControl, etc.) or a type implementing IAddChild.
- If the root must be a FrameworkContentElement, ensure it supports the content model expected by this path.
- Check the type passed to new FrameworkElementFactory(type) — it likely should be a visual/content control.
Example fix
// before var root = new FrameworkElementFactory(typeof(DispatchersObject)); // not FE/FCE/IAddChild // after var root = new FrameworkElementFactory(typeof(Grid));
Defensive patterns
Strategy: type-guard
Validate before calling
if (!typeof(FrameworkElement).IsAssignableFrom(rootType) &&
!typeof(IAddChild).IsAssignableFrom(rootType))
throw new InvalidOperationException($"{rootType.Name} cannot be a factory root"); Type guard
bool IsValidFactoryRoot(Type t) => typeof(FrameworkElement).IsAssignableFrom(t) || typeof(IAddChild).IsAssignableFrom(t);
Try / catch
try { template.LoadContent(); } catch (InvalidOperationException ex) when (ex.Message.Contains("hookup") || ex.Message.Contains("root")) { /* use a supported root type */ } Prevention
- Choose FrameworkElement-derived roots for DataTemplate.VisualTree
- Validate the type passed to the FrameworkElementFactory constructor
- Avoid arbitrary DependencyObjects as template roots
When it happens
Trigger: Using a type as a factory parent (root or interior node) that is neither FrameworkElement, nor handled FrameworkContentElement, nor IAddChild — e.g. an arbitrary DependencyObject or plain object used as the root of a FrameworkElementFactory tree — at template instantiation time.
Common situations: Setting DataTemplate.VisualTree to a factory whose root type cannot host children; using non-visual or non-content types as template roots; typos where the wrong type was passed to the factory constructor.
Understand the failure class
Background: "is not a compatible type" / "cannot merge" errors: when a value's type doesn't match what the library requires — this error's family across 65 libraries.
Related errors
- SR.Format(SR.TemplateMustBeFE, new object[] )
- SR.Format(SR.TypeMustImplementIAddChild…
- SR.Format(SR.TypeMustImplementIAddChild…
- ' ' is not a Visual or Visual3D.
- 0x80070057
AI-assisted analysis of dotnet/wpf@81131a70a4 (2026-09-14).
Data as JSON: /api/errors/3bdc11d92528e513.
Report an issue: GitHub.
Appendix: source
Thrown at src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/FrameworkElementFactory.cs:1119
{
// 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
{
addChildParent.AddChild(treeNodeFCE);
}
}
}
// This method is also used by XamlStyleSerializer to decide whether
// or not to emit the Name attribute for a VisualTree node.
internal bool IsChildNameValid(string childName)View on GitHub (pinned to 81131a70a4)