{"record":{"id":"662352b4392b512f","repo":"locustio/locust","slug":"classname-dest-cannot-be-used-as-a-target-for","errorCode":null,"errorMessage":"{classname}.{dest} cannot be used as a target for a transition since it does not define any transitions of its own.Used as a transition from {task.__name__}.","messagePattern":"(.+?)\\.(.+?) cannot be used as a target for a transition since it does not define any transitions of its own\\.Used as a transition from (.+?)\\.","errorType":"validation","errorClass":"NonMarkovTaskTransitionError","httpStatus":null,"severity":"error","filePath":"locust/user/markov_taskset.py","lineNumber":180,"sourceCode":"    This function checks two conditions for each transition:\n    1. The target task exists in the class\n    2. The target task is also a Markov task (has transitions defined)\n\n    :param tasks: List of Markov tasks to validate\n    :param class_dict: Dictionary containing class attributes and methods\n    :param classname: Name of the class being validated (for error messages)\n    :raises InvalidTransitionError: If a transition points to a non-existent task\n    :raises NonMarkovTaskTransitionError: If a transition points to a task that isn't a Markov task\n    \"\"\"\n    for task in tasks:\n        for dest in task.transitions.keys():\n            dest_task = class_dict.get(dest)\n            if not dest_task:\n                raise InvalidTransitionError(\n                    f\"Transition to {dest} from {task.__name__} is invalid since no such element exists on class {classname}\"\n                )\n            if not is_markov_task(dest_task):\n                raise NonMarkovTaskTransitionError(\n                    f\"{classname}.{dest} cannot be used as a target for a transition since it does not define any transitions of its own.\"\n                    + f\"Used as a transition from {task.__name__}.\"\n                )\n\n\ndef validate_no_unreachable_tasks(tasks: list, class_dict: dict, classname: str):\n    \"\"\"\n    Checks for and warns about unreachable Markov tasks in a MarkovTaskSet.\n\n    This function uses depth-first search (DFS) starting from the first task to identify\n    all reachable tasks. It then warns about any tasks that cannot be reached from the\n    starting task through the defined transitions.\n\n    :param tasks: List of Markov tasks to validate\n    :param class_dict: Dictionary containing class attributes and methods\n    :param classname: Name of the class being validated (for warning messages)\n    :return: The original list of tasks\n    \"\"\"","sourceCodeStart":162,"sourceCodeEnd":198,"githubUrl":"https://github.com/locustio/locust/blob/f391a716e12c2c712e80b5835e877b7933397453/locust/user/markov_taskset.py#L162-L198","documentation":"A Markov transition target must itself be a Markov task, i.e. it must declare its own transitions. Pointing a transition at a plain @task without transitions breaks the chain (the walk could reach a dead end), so NonMarkovTaskTransitionError is raised.","triggerScenarios":"@transition(MyUser.final_step) where final_step is a @task with no @transition decorators of its own; adding a new terminal task and using it as a target from another task.","commonSituations":"Modeling a 'done/end' state as a plain task; forgetting that every reachable state in a Markov chain must define outgoing transitions; converting a plain TaskSet where last methods had no transitions.","solutions":["Give the target task at least one @transition (e.g. back to itself or to another task) so it qualifies as a Markov task","If the state should be terminal, transition it to itself with a weight, or restructure the chain so it isn't a transition target","Verify every @transition destination uses @task together with @transition/@transition_all"],"exampleFix":"// before\n@task\ndef done(self):\n    self.client.get(\"/done\")\n// after\n@task\n@transition(MyUser.done)  # loop back or point to another state\ndef done(self):\n    self.client.get(\"/done\")","handlingStrategy":"validation","validationCode":"for t in MyUser.__dict__.values():\n    for dest in getattr(t, \"transitions\", {}):\n        assert getattr(MyUser.__dict__.get(dest), \"transitions\", None), f\"{dest} is not a Markov task\"","typeGuard":null,"tryCatchPattern":"try:\n    validate_markov_chain(tasks, dict(vars(MyUser)), MyUser.__name__)\nexcept NonMarkovTaskTransitionError as e:\n    logging.error(e)\n    raise","preventionTips":["Give every transition-reachable task its own @transition","Model terminal states as self-transitions","Validate chains in unit tests before running load tests"],"tags":["locust","markov-taskset","transition","chain-validity"],"backgroundTag":"invalid-transition-target","analyzedSha":"f391a716e12c2c712e80b5835e877b7933397453","analyzedAt":"2026-08-29T00:36:13.872Z","schemaVersion":2},"datasetVersion":"2026-08-29T02:17:18.158Z"}