locustio/locust · error · NoMarkovTasksError
No Markov tasks defined in class {classname}. Use the @trans
Error message
No Markov tasks defined in class {classname}. Use the @transition(s) decorators to define some. What it means
A MarkovTaskSet subclass must define at least one @task whose transitions are declared via the @transition/@transition_all decorators. validate_has_markov_tasks raises NoMarkovTasksError when the class defines no Markov tasks, because the Markov chain would have no states to traverse.
Source
Thrown at locust/user/markov_taskset.py:153
def to_weighted_list(transitions: dict):
return [name for name in transitions.keys() for _ in range(transitions[name])]
def validate_has_markov_tasks(tasks: list, classname: str):
"""
Validates that a MarkovTaskSet has at least one Markov task.
This function is used internally during MarkovTaskSet validation to ensure
that the class has at least one method decorated with @transition or @transitions.
:param tasks: List of tasks to validate
:param classname: Name of the class being validated (for error messages)
:raises NoMarkovTasksError: If no Markov tasks are found
"""
if not tasks:
raise NoMarkovTasksError(
f"No Markov tasks defined in class {classname}. Use the @transition(s) decorators to define some."
)
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
"""View on GitHub (pinned to f391a716e1)
Solutions
- Add @task decorated methods and mark transitions between them with @transition(MyUser.task_b, weight=...)
- If no Markov behavior is needed, inherit from TaskSet/SequentialTaskSet instead of MarkovTaskSet
- Copy a minimal MarkovTaskSet example and add your own states
Example fix
// before
class MyUser(MarkovTaskSet):
def browse(self):
self.client.get("/")
// after
class MyUser(MarkovTaskSet):
@task
@transition(MyUser.checkout)
def browse(self):
self.client.get("/")
@task
def checkout(self):
self.client.post("/checkout") Defensive patterns
Strategy: validation
Validate before calling
assert any(hasattr(m, "transitions") for m in vars(MyUser).values()), "MarkovTaskSet needs @transition-decorated tasks"
Try / catch
try:
user = MyUser(env)
except NoMarkovTasksError as e:
logging.error(f"Fix class definition: {e}")
raise Prevention
- Always pair @task with @transition in MarkovTaskSet classes
- Start from a working MarkovTaskSet example template
- Use a plain TaskSet when Markov semantics are not needed
When it happens
Trigger: Defining 'class MyUser(MarkovTaskSet)' with no @task/@transition methods at all, or only plain methods with no transition decorators, then instantiating or validating the class.
Common situations: Migrating a regular TaskSet to MarkovTaskSet and forgetting the @transition decorators; leaving a placeholder class empty; typos such as using @task without @transition and assuming tasks alone are enough.
Related errors
- You must specify the base host. Either in the host attribute
- StatsEntry.use_response_times_cache must be set to True to c
- Transition to {dest} from {task.__name__} is invalid since n
- {classname}.{dest} cannot be used as a target for a transiti
- Tags are unsupported for MarkovTaskSet since they can make t
AI-assisted analysis of locustio/locust@f391a716e1 (2026-08-29).
Data as JSON: /api/errors/bcafb205183d3e3d.
Report an issue: GitHub.