{"record":{"id":"5c47ae10f14605c4","repo":"AtsushiSakai/PythonRobotics","slug":"children-are-not-set","errorCode":null,"errorMessage":"Children are not set","messagePattern":"Children are not set","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"MissionPlanning/BehaviorTree/behavior_tree.py","lineNumber":84,"sourceCode":"        pass\n\n\nclass ControlNode(Node):\n    \"\"\"\n    Base class for all control nodes in a behavior tree.\n\n    Control nodes manage the execution flow of their child nodes according to specific rules.\n    They typically have multiple children and determine which children to execute and in what order.\n    \"\"\"\n\n    def __init__(self, name):\n        super().__init__(name)\n        self.children = []\n        self.type = NodeType.CONTROL_NODE\n\n    def not_set_children_raise_error(self):\n        if len(self.children) == 0:\n            raise ValueError(\"Children are not set\")\n\n    def reset_children(self):\n        for child in self.children:\n            child.reset()\n\n\nclass SequenceNode(ControlNode):\n    \"\"\"\n    Executes child nodes in sequence until one fails or all succeed.\n\n    Returns:\n        - Returns FAILURE if any child returns FAILURE\n        - Returns SUCCESS when all children have succeeded\n        - Returns RUNNING when a child is still running or when moving to the next child\n\n    Example:\n        .. code-block:: xml\n","sourceCodeStart":66,"sourceCodeEnd":102,"githubUrl":"https://github.com/AtsushiSakai/PythonRobotics/blob/1fe4fb980f6a12fe21c3c33d2b4da97a52c9154d/MissionPlanning/BehaviorTree/behavior_tree.py#L66-L102","documentation":"Raised by ControlNode.not_set_children_raise_error, called from tick. A control node (sequence, selector, while-do-else) cannot execute without at least one child, so ticking an empty control node is rejected.","triggerScenarios":"Creating a SequenceNode/SelectorNode/WhileDoElseNode, never calling add_child, and then ticking the tree containing it. Also triggered by building a tree from XML where a control tag has no child tags.","commonSituations":"Dynamically assembled trees where children are conditionally appended and the list ends up empty, or XML tree definitions with a control node that has no children.","solutions":["Add at least one child node via add_child before ticking.","Validate the tree structure after construction (len(node.children) > 0).","If loading from XML, ensure every control tag encloses at least one child element."],"exampleFix":"// before\nseq = SequenceNode('seq')\ntree.tick()  # no children added\n\n// after\nseq = SequenceNode('seq')\nseq.add_child(ActionA('a'))\ntree.tick()","handlingStrategy":"validation","validationCode":"assert len(control_node.children) > 0, f'{control_node.name} has no children'","typeGuard":"def has_children(node) -> bool:\n    return getattr(node, 'children', None) and len(node.children) > 0","tryCatchPattern":"try:\n    tree.tick()\nexcept ValueError as e:\n    if 'Children are not set' in str(e):\n        # attach children or skip this tick\n        pass\n    raise","preventionTips":["Build trees through a factory that validates structure before returning.","Treat empty control nodes as a build-time error, not runtime."],"tags":["behavior-tree","control-node","validation"],"backgroundTag":"empty-children-not-allowed","analyzedSha":"1fe4fb980f6a12fe21c3c33d2b4da97a52c9154d","analyzedAt":"2026-08-28T13:23:33.733Z","schemaVersion":2},"datasetVersion":"2026-08-28T16:17:29.566Z"}