locustio/locust · error · MarkovTaskTagError
Tags are unsupported for MarkovTaskSet since they can make t
Error message
Tags are unsupported for MarkovTaskSet since they can make the markov chain invalid. Tags detected on {classname}.{task.__name__}: {task.locust_tag_set} What it means
Tags would let runs select/reject individual states, which can remove nodes from the Markov chain and invalidate transition probabilities. validate_no_tags raises MarkovTaskTagError if any task in a MarkovTaskSet carries @tag/@tags (detected via the locust_tag_set attribute).
Source
Thrown at locust/user/markov_taskset.py:229
if len(unreachable) > 0:
logging.warning(f"The following markov tasks are unreachable in class {classname}: {unreachable}")
return tasks
def validate_no_tags(task, classname: str):
"""
Validates that Markov tasks don't have tags, which are unsupported.
Tags are not supported for MarkovTaskSet because they can make the Markov chain invalid
by potentially filtering out tasks that are part of the chain.
:param task: The task to validate
:param classname: Name of the class being validated (for error messages)
:raises MarkovTaskTagError: If the task has tags
"""
if "locust_tag_set" in dir(task):
raise MarkovTaskTagError(
"Tags are unsupported for MarkovTaskSet since they can make the markov chain invalid. "
+ f"Tags detected on {classname}.{task.__name__}: {task.locust_tag_set}"
)
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"
"""View on GitHub (pinned to f391a716e1)
Solutions
- Remove @tag/@tags decorators from all tasks in MarkovTaskSet classes
- If you need to subset runs, split the Markov chain into separate MarkovTaskSet classes instead of using tags
- Use a regular TaskSet if tag-based task filtering is essential to your test
Example fix
// before
@task
@tag("smoke")
@transition(MyUser.next_step)
def browse(self): ...
// after
@task
@transition(MyUser.next_step)
def browse(self): ... Defensive patterns
Strategy: validation
Validate before calling
for name, m in vars(MyUser).items():
assert "locust_tag_set" not in dir(m), f"tags not allowed on {name} in MarkovTaskSet" Try / catch
try:
user = MyUser(env)
except MarkovTaskTagError as e:
logging.error(e)
raise Prevention
- Never apply @tag/@tags inside MarkovTaskSet classes
- Subset Markov tests by launching separate classes instead of tags
- Review imports/copies from regular TaskSets for leftover decorators
When it happens
Trigger: Applying @tag("smoke") or @tags([...]) to a @task method inside a MarkovTaskSet class, then running/validating the class.
Common situations: Copy-pasting tagged tasks from a regular TaskSet into a MarkovTaskSet; using tags to subset a smoke-test run on a Markov flow; mixed TaskSet/MarkovTaskSet codebases applying tags uniformly.
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
- 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/07d844876d243d5b.
Report an issue: GitHub.