{"record":{"id":"0709ff3a1a77a14d","repo":"AtsushiSakai/PythonRobotics","slug":"child-is-not-set","errorCode":null,"errorMessage":"Child is not set","messagePattern":"Child is not set","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"MissionPlanning/BehaviorTree/behavior_tree.py","lineNumber":305,"sourceCode":"        return Status.SUCCESS\n\n\nclass DecoratorNode(Node):\n    \"\"\"\n    Base class for all decorator nodes in a behavior tree.\n\n    Decorator nodes modify the behavior of their child node.\n    They must have a single child and can alter the status of the child node.\n    \"\"\"\n\n    def __init__(self, name):\n        super().__init__(name)\n        self.type = NodeType.DECORATOR_NODE\n        self.child = None\n\n    def not_set_child_raise_error(self):\n        if self.child is None:\n            raise ValueError(\"Child is not set\")\n\n    def reset_children(self):\n        self.child.reset()\n\n\nclass InverterNode(DecoratorNode):\n    \"\"\"\n    Inverter node that inverts the status of its child node.\n\n    Returns:\n        - Returns SUCCESS if the child returns FAILURE\n        - Returns FAILURE if the child returns SUCCESS\n        - Returns RUNNING if the child returns RUNNING\n\n    Examples:\n        .. code-block:: xml\n\n            <Inverter>","sourceCodeStart":287,"sourceCodeEnd":323,"githubUrl":"https://github.com/AtsushiSakai/PythonRobotics/blob/1fe4fb980f6a12fe21c3c33d2b4da97a52c9154d/MissionPlanning/BehaviorTree/behavior_tree.py#L287-L323","documentation":"Raised by DecoratorNode.not_set_child_raise_error, called from tick. Decorators (inverter, retry, etc.) wrap exactly one child; ticking one whose child was never assigned is rejected.","triggerScenarios":"Creating an InverterNode (or other decorator), not setting .child (e.g. not calling set_child / not configuring via the XML builder), and ticking the tree.","commonSituations":"Programmatically building a tree and forgetting to attach the wrapped node, or XML where the decorator tag is empty.","solutions":["Set the decorator's child (root.child = inner_node) before ticking.","When loading from XML, give the decorator tag exactly one child element.","Tree-validate after construction: assert decorator.child is not None."],"exampleFix":"// before\ninv = InverterNode('inv')\ntree.tick()  # child never set\n\n// after\ninv = InverterNode('inv')\ninv.child = my_action\ntree.tick()","handlingStrategy":"validation","validationCode":"assert decorator.child is not None, f'{decorator.name} has no child'","typeGuard":"def has_child(node) -> bool:\n    return getattr(node, 'child', None) is not None","tryCatchPattern":null,"preventionTips":["When building trees programmatically, set decorator.child immediately after construction.","Validate the whole tree recursively before the first tick."],"tags":["behavior-tree","decorator-node","validation"],"backgroundTag":"missing-required-child-node","analyzedSha":"1fe4fb980f6a12fe21c3c33d2b4da97a52c9154d","analyzedAt":"2026-08-28T13:23:33.733Z","schemaVersion":2},"datasetVersion":"2026-08-28T16:17:29.566Z"}