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

  1. Register only the most-derived (or only the base) type of each hierarchy branch as a root — never both a parent and its descendant
  2. After refactoring the message hierarchy, re-audit the root type list with a test asserting no root is assignable to another
  3. 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

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


AI-assisted analysis of microsoft/autogen@027ecf0a37 (2026-08-15). Data as JSON: /api/errors/0e3d8cfbe049ff97. Report an issue: GitHub.