microsoft/autogen · error · ArgumentException
Root types cannot be derived from each other: {rootType.Name
Error message
Root types cannot be derived from each other: {rootType.Name} What it means
TypeTree, used for polymorphic serialization of the AgentMessage hierarchy, requires its root types to be mutually unrelated: no root may be assignable to or from another root (t.IsAssignableFrom(rootType) || rootType.IsAssignableFrom(t)). Violating this makes the subtype mapping ambiguous, so the constructor throws ArgumentException naming the offending rootType.
Source
Thrown at dotnet/src/Microsoft.AutoGen/AgentChat/Abstractions/Messages.cs:706
parentNode.Children.Add(currentNode);
currentNode = parentNode;
}
}
public HashSet<Type> RootTypes { get; }
public Dictionary<Type, TypeNode> TypeNodes { get; } = new Dictionary<Type, TypeNode>();
public TypeTree(params Type[] rootTypes)
{
this.RootTypes = new HashSet<Type>();
foreach (var rootType in rootTypes)
{
// Check that there are no other types that this type derives from in the root types
// or vice versa
if (this.RootTypes.Any(t => t.IsAssignableFrom(rootType) || rootType.IsAssignableFrom(t)))
{
throw new ArgumentException($"Root types cannot be derived from each other: {rootType.Name}");
}
this.RootTypes.Add(rootType);
this.EnsureType(rootType);
foreach (var derivedType in GetDerivedTypes(rootType))
{
this.EnsureType(derivedType);
}
}
}
}
internal static readonly TypeTree MessageTypeTree = new(typeof(AgentMessage), typeof(GroupChatEventBase));
internal sealed class MessagesTypeInfoResolver : DefaultJsonTypeInfoResolver
{View on GitHub (pinned to 027ecf0a37)
Solutions
- Register only the most-derived (or only the base) type of each hierarchy branch as a root — never both a parent and its descendant
- After refactoring the message hierarchy, re-audit the root type list with a test asserting no root is assignable to another
- Use the smallest set of roots: TypeTree walks derived types itself via GetDerivedTypes
Example fix
// before var tree = new TypeTree(typeof(ChatMessage), typeof(TextMessage)); // TextMessage : ChatMessage // after var tree = new TypeTree(typeof(ChatMessage)); // derived types are discovered automatically
Defensive patterns
Strategy: validation
Validate before calling
bool RootsAreUnrelated(Type[] roots) => roots.All(a => roots.Where(b => b != a).All(b => !a.IsAssignableFrom(b) && !b.IsAssignableFrom(a)));
if (!RootsAreUnrelated(roots)) throw new ArgumentException("TypeTree roots must not derive from each other");
var tree = new TypeTree(roots); Type guard
static bool AreUnrelatedRoots(Type a, Type b) => !a.IsAssignableFrom(b) && !b.IsAssignableFrom(a);
Prevention
- Register only one type per inheritance branch as a TypeTree root
- Add a startup/test assertion that no root is assignable to another root
- After hierarchy refactors, re-run the serialization test suite that exercises TypeTree construction
When it happens
Trigger: Constructing a TypeTree with two roots where one derives from the other, e.g. TypeTree(typeof(ChatMessage), typeof(AgentEvent)) when AgentEvent derives from a common base also listed, or custom message types that inherit from each other supplied as separate roots.
Common situations: Extending the message hierarchy with custom base/derived pairs and registering both as roots; refactoring message types so a previously unrelated pair becomes parent/child without updating TypeTree construction; copy-pasted root lists drifting out of sync with the class hierarchy.
Related errors
- ImageMessage must have Url or DataUri
- Unsupported content type {item.GetType()}
- Unsupported config type {llmConfig.GetType()}
- Invalid mode
- Agent name '{name}' is not a valid identifier.
AI-assisted analysis of microsoft/autogen@027ecf0a37 (2026-08-15).
Data as JSON: /api/errors/0e3d8cfbe049ff97.
Report an issue: GitHub.