locustio/locust · error · InvalidTransitionError

Transition to {dest} from {task.__name__} is invalid since n

Error message

Transition to {dest} from {task.__name__} is invalid since no such element exists on class {classname}

What it means

Every transition target in a MarkovTaskSet must exist as an element on the class. validate_transitions raises InvalidTransitionError when task.transitions references a name that is not found in the class dict — the destination state simply does not exist.

Source

Thrown at locust/user/markov_taskset.py:176

def validate_transitions(tasks: list, class_dict: dict, classname: str):
    """
    Validates that all transitions in Markov tasks point to existing Markov tasks.

    This function checks two conditions for each transition:
    1. The target task exists in the class
    2. The target task is also a Markov task (has transitions defined)

    :param tasks: List of Markov tasks to validate
    :param class_dict: Dictionary containing class attributes and methods
    :param classname: Name of the class being validated (for error messages)
    :raises InvalidTransitionError: If a transition points to a non-existent task
    :raises NonMarkovTaskTransitionError: If a transition points to a task that isn't a Markov task
    """
    for task in tasks:
        for dest in task.transitions.keys():
            dest_task = class_dict.get(dest)
            if not dest_task:
                raise InvalidTransitionError(
                    f"Transition to {dest} from {task.__name__} is invalid since no such element exists on class {classname}"
                )
            if not is_markov_task(dest_task):
                raise NonMarkovTaskTransitionError(
                    f"{classname}.{dest} cannot be used as a target for a transition since it does not define any transitions of its own."
                    + f"Used as a transition from {task.__name__}."
                )


def validate_no_unreachable_tasks(tasks: list, class_dict: dict, classname: str):
    """
    Checks for and warns about unreachable Markov tasks in a MarkovTaskSet.

    This function uses depth-first search (DFS) starting from the first task to identify
    all reachable tasks. It then warns about any tasks that cannot be reached from the
    starting task through the defined transitions.

    :param tasks: List of Markov tasks to validate

View on GitHub (pinned to f391a716e1)

Solutions

  1. Correct the transition target name so it matches a @task method defined on the same MarkovTaskSet class
  2. Define the missing task method on the class
  3. Ensure the target is a method of this class, not an external function or inherited method that the validator cannot see

Example fix

// before
@task
@transition(MyUser.chekout)
def browse(self): ...
// after
@task
@transition(MyUser.checkout)
def browse(self): ...
Defensive patterns

Strategy: validation

Validate before calling

for t in MyUser.__dict__.values():
    for dest in getattr(t, "transitions", {}):
        assert dest in MyUser.__dict__, f"unknown transition target {dest}"

Try / catch

try:
    validate_markov_chain(tasks, dict(vars(MyUser)), MyUser.__name__)
except InvalidTransitionError as e:
    logging.error(e)
    raise

Prevention

When it happens

Trigger: @transition(SomeTask) where SomeTask is spelled wrong, defined in another class, deleted in a refactor, or the target was defined after the decorator referencing it failed to resolve.

Common situations: Renaming a task method without updating @transition calls; copying transition definitions between classes; referencing tasks defined on a parent class or imported module not present in the class being validated.

Related errors


AI-assisted analysis of locustio/locust@f391a716e1 (2026-08-29). Data as JSON: /api/errors/bcb5fa4dc89e3c25. Report an issue: GitHub.