dotnet/wpf · error · InvalidOperationException
SR.Format(SR.TypeMustImplementIAddChild…
Error message
SR.Format(SR.TypeMustImplementIAddChild, frameworkObject.DO.GetType().Name)
What it means
In InstantiateUnoptimizedTree, when the current node has a childFactory, the framework expects the instantiated parent object to implement IAddChild so the child can be attached. If frameworkObject.DO does not implement IAddChild, an InvalidOperationException naming the parent's type is thrown. This guards the child-attachment contract during template instantiation.
Solutions
- Choose an interior parent type that implements IAddChild (e.g. ContentControl, Panel types, Decorator).
- Implement IAddChild on the custom parent type.
- Restructure the factory tree so children attach through the parent's native content property instead of AppendChild.
Example fix
// before
var root = new FrameworkElementFactory(typeof(MyControl)); // MyControl has no IAddChild
root.AppendChild(new FrameworkElementFactory(typeof(Button)));
// after
class MyControl : ContentControl { ... } // or use ContentControl directly Defensive patterns
Strategy: type-guard
Validate before calling
if (rootFactory.Type != null && !typeof(IAddChild).IsAssignableFrom(rootFactory.Type) && rootHasChildren)
throw new InvalidOperationException($"{rootFactory.Type.Name} cannot host child factories"); Type guard
bool SupportsChildren(Type t) => typeof(IAddChild).IsAssignableFrom(t);
Try / catch
try { template.LoadContent(); } catch (InvalidOperationException ex) when (ex.Message.Contains("IAddChild")) { /* replace root/parent type */ } Prevention
- Only AppendChild onto factories whose type implements IAddChild
- Prefer standard controls (Grid, StackPanel, ContentControl) as interior nodes
- Recheck compatibility after upgrading custom control libraries
When it happens
Trigger: A FrameworkElementFactory tree where node A has appended children (childFactory != null) and A's type, when instantiated, does not implement IAddChild; triggered when the template tree is instantiated unoptimized.
Common situations: Appending child factories to a parent type that only accepts children through a specialized API (not IAddChild); custom controls used as template roots/interior nodes; version changes where a control no longer implements IAddChild.
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.TypeMustImplementIAddChild…
- SR.Format(SR.CannotHookupFCERoot, type.Name)
- SR.Format(SR.TemplateMustBeFE, new object[] )
- SR.Format(SR.TypeMustImplementIAddChild, _type.Name)
- ' ' is not a Visual or Visual3D.
AI-assisted analysis of dotnet/wpf@81131a70a4 (2026-09-14).
Data as JSON: /api/errors/625944eb8f3325da.
Report an issue: GitHub.
Appendix: source
Thrown at src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/FrameworkElementFactory.cs:951
// Set values for this object, taking them from the shared values table.
ProvideValueServiceProvider provideValueServiceProvider = null;
FrameworkTemplate.SetTemplateParentValues( Name, frameworkObject.DO, _frameworkTemplate, ref provideValueServiceProvider );
// Get the first child
FrameworkElementFactory childFactory = _firstChild;
// If we have children, get this object's IAddChild, because it's going to be a parent.
IAddChild iAddChild = null;
if( childFactory != null )
{
iAddChild = frameworkObject.DO as IAddChild;
if (iAddChild == null)
{
throw new InvalidOperationException(SR.Format(SR.TypeMustImplementIAddChild,
frameworkObject.DO.GetType().Name));
}
}
// Build the children.
while (childFactory != null)
{
if (childFactory._text != null)
{
iAddChild.AddText(childFactory._text);
}
else
{
// Use frameworkObject's IAddChild to add this node.
FrameworkObject childFrameworkObject = childFactory.InstantiateUnoptimizedTree();View on GitHub (pinned to 81131a70a4)