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 validateView on GitHub (pinned to f391a716e1)
Solutions
- Correct the transition target name so it matches a @task method defined on the same MarkovTaskSet class
- Define the missing task method on the class
- 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
- Rename task methods together with their transition references (IDE rename refactor)
- Grep for @transition targets when adding/removing tasks
- Run a smoke instantiation of MarkovTaskSet classes in CI
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
- {classname}.{dest} cannot be used as a target for a transiti
- No Markov tasks defined in class {classname}. Use the @trans
- Tags are unsupported for MarkovTaskSet since they can make t
- TaskSet.run() is a method used internally by Locust, and you
- In order to use a with-block for requests, you must also pas
AI-assisted analysis of locustio/locust@f391a716e1 (2026-08-29).
Data as JSON: /api/errors/bcb5fa4dc89e3c25.
Report an issue: GitHub.