{"record":{"id":"b8b3d59c4db6ca41","repo":"AtsushiSakai/PythonRobotics","slug":"root-name-control-node-must-have-children","errorCode":null,"errorMessage":"{root.name} Control node must have children","messagePattern":"(.+?) Control node must have children","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"MissionPlanning/BehaviorTree/behavior_tree.py","lineNumber":627,"sourceCode":"                )\n        \"\"\"\n        self.node_builders[node_name] = builder\n\n    def build_node(self, node):\n        \"\"\"\n        Build a node from an XML element.\n\n        Args:\n            node (Element): The XML element to build the node from.\n\n        Returns:\n            BehaviorTree Node: the built node\n        \"\"\"\n        if node.tag in self.node_builders:\n            root = self.node_builders[node.tag](node)\n            if root.type == NodeType.CONTROL_NODE:\n                if len(node) <= 0:\n                    raise ValueError(f\"{root.name} Control node must have children\")\n                for child in node:\n                    root.children.append(self.build_node(child))\n            elif root.type == NodeType.DECORATOR_NODE:\n                if len(node) != 1:\n                    raise ValueError(\n                        f\"{root.name} Decorator node must have exactly one child\"\n                    )\n                root.child = self.build_node(node[0])\n            elif root.type == NodeType.ACTION_NODE:\n                if len(node) != 0:\n                    raise ValueError(f\"{root.name} Action node must have no children\")\n            return root\n        else:\n            raise ValueError(f\"Unknown node type: {node.tag}\")\n\n    def build_tree(self, xml_string):\n        \"\"\"\n        Build a behavior tree from an XML string.","sourceCodeStart":609,"sourceCodeEnd":645,"githubUrl":"https://github.com/AtsushiSakai/PythonRobotics/blob/1fe4fb980f6a12fe21c3c33d2b4da97a52c9154d/MissionPlanning/BehaviorTree/behavior_tree.py#L609-L645","documentation":"Raised by BehaviorTree XML builder's build_node when a control-node tag (sequence, selector, while-do-else) contains no child elements. Control nodes need children to execute, so an empty tag in the XML is a structural error.","triggerScenarios":"Parsing XML like <Sequence name=\"s\"/> or <Sequence name=\"s\"></Sequence> with build_tree/build_node.","commonSituations":"Hand-written or template-generated XML tree files where a control tag is left empty or children are commented out.","solutions":["Add at least one child element inside the control tag in the XML.","Validate the XML against your tree schema before build_tree.","Check for self-closing control tags (<Sequence .../>)."],"exampleFix":"<!-- before -->\n<Sequence name=\"s\"/>\n\n<!-- after -->\n<Sequence name=\"s\">\n  <ActionA name=\"a\"/>\n</Sequence>","handlingStrategy":"validation","validationCode":"import xml.etree.ElementTree as ET\nroot = ET.fromstring(xml_string)\nfor el in root.iter():\n    if el.tag in CONTROL_TAGS and len(el) == 0:\n        raise ValueError(f'{el.tag} {el.get(\"name\")} has no children')","typeGuard":null,"tryCatchPattern":"try:\n    tree = builder.build_tree(xml_string)\nexcept ValueError as e:\n    if 'must have children' in str(e):\n        fix_and_retry(xml_string)\n    raise","preventionTips":["Lint behavior-tree XML before runtime (schema or simple ElementTree checks).","Watch for self-closing control tags."],"tags":["behavior-tree","xml-parsing","validation"],"backgroundTag":"xml-schema-validation-failed","analyzedSha":"1fe4fb980f6a12fe21c3c33d2b4da97a52c9154d","analyzedAt":"2026-08-28T13:23:33.733Z","schemaVersion":2},"datasetVersion":"2026-08-28T16:17:29.566Z"}