locustio/locust · error · Exception
TaskSet.run() is a method used internally by Locust, and you
Error message
TaskSet.run() is a method used internally by Locust, and you must not override it or annotate it with transitions
What it means
TaskSet.run() is Locust's internal execution loop. Overriding it — or annotating a method named 'run' with @transition — would corrupt the MarkovTaskSet machinery, so validate_task_name raises immediately when a decorated function is named 'run'.
Source
Thrown at locust/user/markov_taskset.py:253
def validate_task_name(decorated_func):
"""
Validates that certain method names aren't used as Markov tasks.
This function checks for special method names that shouldn't be used as Markov tasks:
- "on_stop" and "on_start": Using these as Markov tasks will cause them to be called
both as tasks AND on stop/start, which is usually not what the user intended.
- "run": This method is used internally by Locust and must not be overridden or
annotated with transitions.
:param decorated_func: The function to validate
:raises Exception: If the function name is "run"
"""
if decorated_func.__name__ in ["on_stop", "on_start"]:
logging.warning(
"You have tagged your on_stop/start function with @transition. This will make the method get called both as a step AND on stop/start."
) # this is usually not what the user intended
if decorated_func.__name__ == "run":
raise Exception(
"TaskSet.run() is a method used internally by Locust, and you must not override it or annotate it with transitions"
)
def validate_markov_chain(tasks: list, class_dict: dict, classname: str):
"""
Runs all validation functions on a Markov chain.
: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/warning messages)
:raises: Various exceptions if validation fails
"""
validate_has_markov_tasks(tasks, classname)
validate_transitions(tasks, class_dict, classname)
validate_no_unreachable_tasks(tasks, class_dict, classname)
for task in tasks:
validate_task_name(task)View on GitHub (pinned to f391a716e1)
Solutions
- Rename the method to something else, e.g. 'run_job', and update transitions accordingly
- Move any custom loop logic out of run() — let Locust's TaskSet.run drive the chain
- If you need lifecycle behavior, use on_start/on_stop instead of overriding run
Example fix
// before @task @transition(MyUser.next) def run(self): ... // after @task @transition(MyUser.next) def run_job(self): ...
Defensive patterns
Strategy: validation
Validate before calling
assert not any(name == "run" for name in vars(MyUser)), "'run' is reserved in MarkovTaskSet"
Try / catch
try:
user = MyUser(env)
except Exception as e:
if "must not override" in str(e):
logging.error("Rename the 'run' method")
raise Prevention
- Avoid method names matching TaskSet internals (run, on_start, on_stop)
- Name domain actions descriptively (run_job, run_report)
- Check Locust TaskSet docs for reserved method names
When it happens
Trigger: Defining 'def run(self):' decorated with @task/@transition inside a MarkovTaskSet; porting a TaskSet that overrode run() to MarkovTaskSet.
Common situations: Naming a task 'run' because the domain action is called that (e.g. 'run job'); copy-pasted legacy TaskSet code that overrode run for custom looping.
Related errors
- No Markov tasks defined in class {classname}. Use the @trans
- 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
- 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/6c0dc1bceb5e2b87.
Report an issue: GitHub.