AtsushiSakai/PythonRobotics · error · ValueError

Unknown status

Error message

Unknown status

What it means

SequenceNode.tick raises this when a child returns a Status value outside SUCCESS/FAILURE/RUNNING. The final else branch guards against corrupted or custom statuses, indicating a child node misbehaving.

Source

Thrown at MissionPlanning/BehaviorTree/behavior_tree.py:129

        self.current_child_index = 0

    def tick(self) -> Status:
        self.not_set_children_raise_error()

        if self.current_child_index >= len(self.children):
            self.reset_children()
            return Status.SUCCESS
        status = self.children[self.current_child_index].tick_and_set_status()
        if status == Status.FAILURE:
            self.reset_children()
            return Status.FAILURE
        elif status == Status.SUCCESS:
            self.current_child_index += 1
            return Status.RUNNING
        elif status == Status.RUNNING:
            return Status.RUNNING
        else:
            raise ValueError("Unknown status")


class SelectorNode(ControlNode):
    """
    Executes child nodes in sequence until one succeeds or all fail.

    Returns:
        - Returns SUCCESS if any child returns SUCCESS
        - Returns FAILURE when all children have failed
        - Returns RUNNING when a child is still running or when moving to the next child

    Examples:
        .. code-block:: xml

            <Selector>
                <Action1 />
                <Action2 />
            </Selector>

View on GitHub (pinned to 1fe4fb980f)

Solutions

  1. Make every custom tick method return one of Status.SUCCESS, Status.FAILURE, Status.RUNNING.
  2. Check the child returning the unexpected value; log its return type before it reaches the sequence.
  3. Use tick_and_set_status so the node's stored status reveals the offending node.

Example fix

// before
class Go(ActionNode):
    def tick(self):
        do_work()  # returns None

// after
class Go(ActionNode):
    def tick(self):
        do_work()
        return Status.RUNNING
Defensive patterns

Strategy: validation

Type guard

from MissionPlanning.BehaviorTree.behavior_tree import Status

def valid_status(s) -> bool:
    return isinstance(s, Status)

Try / catch

try:
    seq.tick_and_set_status()
except ValueError as e:
    if 'Unknown status' in str(e):
        log_child_statuses(seq)  # inspect children to find the bad node
    raise

Prevention

When it happens

Trigger: A child node's tick returns None (forgot a return statement), an int, or a custom status not in the Status enum, and the sequence node propagates ticks to it.

Common situations: Writing a custom action node whose tick forgets to return, or returns a raw string instead of Status.SUCCESS.

Related errors


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