AtsushiSakai/PythonRobotics · error · ValueError

{root.name} Decorator node must have exactly one child

Error message

{root.name} Decorator node must have exactly one child

What it means

Raised by build_node when a decorator-node tag in the XML does not contain exactly one child element. Decorators wrap a single node, so zero or multiple children are structural errors.

Source

Thrown at MissionPlanning/BehaviorTree/behavior_tree.py:632

        """
        Build a node from an XML element.

        Args:
            node (Element): The XML element to build the node from.

        Returns:
            BehaviorTree Node: the built node
        """
        if node.tag in self.node_builders:
            root = self.node_builders[node.tag](node)
            if root.type == NodeType.CONTROL_NODE:
                if len(node) <= 0:
                    raise ValueError(f"{root.name} Control node must have children")
                for child in node:
                    root.children.append(self.build_node(child))
            elif root.type == NodeType.DECORATOR_NODE:
                if len(node) != 1:
                    raise ValueError(
                        f"{root.name} Decorator node must have exactly one child"
                    )
                root.child = self.build_node(node[0])
            elif root.type == NodeType.ACTION_NODE:
                if len(node) != 0:
                    raise ValueError(f"{root.name} Action node must have no children")
            return root
        else:
            raise ValueError(f"Unknown node type: {node.tag}")

    def build_tree(self, xml_string):
        """
        Build a behavior tree from an XML string.

        Args:
            xml_string (str): The XML string containing the behavior tree.

        Returns:

View on GitHub (pinned to 1fe4fb980f)

Solutions

  1. Give the decorator tag exactly one child element in the XML.
  2. Move extra children out or wrap them in a sequence under the decorator.
  3. Lint the XML tree structure before calling build_tree.

Example fix

<!-- before -->
<Inverter name="i">
  <ActionA name="a"/>
  <ActionB name="b"/>
</Inverter>

<!-- after -->
<Inverter name="i">
  <Sequence name="s">
    <ActionA name="a"/>
    <ActionB name="b"/>
  </Sequence>
</Inverter>
Defensive patterns

Strategy: validation

Validate before calling

for el in root.iter():
    if el.tag in DECORATOR_TAGS and len(el) != 1:
        raise ValueError(f'{el.tag} {el.get("name")} must have exactly one child')

Try / catch

try:
    tree = builder.build_tree(xml_string)
except ValueError as e:
    if 'exactly one child' in str(e):
        wrap_extra_children_in_sequence(xml_string)
    raise

Prevention

When it happens

Trigger: XML like <Inverter name="i"/> (zero children) or an Inverter enclosing two child tags.

Common situations: Nesting mistakes in hand-authored XML, or copying a control-node pattern under a decorator tag.

Related errors


AI-assisted analysis of AtsushiSakai/PythonRobotics@1fe4fb980f (2026-08-28). Data as JSON: /api/errors/e34c7cece526d06d. Report an issue: GitHub.