locustio/locust · error · ValueError

Unrecognized task type in user

Error message

Unrecognized task type in user

What it means

When assign_equal_weights() flattens a user's task set, each entry must be either a TaskHolder (e.g. TaskSet/nested class) or a callable (@task method). Anything else is invalid and raises ValueError.

Source

Thrown at locust/env.py:287

    def assign_equal_weights(self) -> None:
        """
        Update the user classes such that each user runs their specified tasks with equal
        probability.
        """
        for u in self.user_classes:
            u.weight = 1
            user_tasks: list[TaskSet | Callable] = []
            tasks_frontier = u.tasks
            while len(tasks_frontier) != 0:
                t = tasks_frontier.pop()
                if isinstance(t, TaskHolder):
                    tasks_frontier.extend(t.tasks)
                elif callable(t):
                    if t not in user_tasks:
                        user_tasks.append(t)
                else:
                    raise ValueError("Unrecognized task type in user")
            u.tasks = user_tasks

    def _validate_user_class_name_uniqueness(self):
        # Validate there's no class with the same name but in different modules
        if len({user_class.__name__ for user_class in self.user_classes}) != len(self.user_classes):
            raise ValueError(
                "The following user classes have the same class name: {}".format(
                    ", ".join(map(methodcaller("fullname"), self.user_classes))
                )
            )

    def _validate_shape_class_instance(self):
        if self.shape_class is not None and not isinstance(self.shape_class, LoadTestShape):
            raise ValueError(
                f"shape_class should be instance of LoadTestShape or subclass LoadTestShape, but got: {self.shape_class}"
            )

    @property

View on GitHub (pinned to f391a716e1)

Solutions

  1. Ensure every item in `tasks` is either a callable decorated with @task or a TaskSet/TaskHolder subclass
  2. Remove or fix entries that are instances, strings, or other objects
  3. Use the @task decorator instead of manual list manipulation

Example fix

// before
MyUser.tasks = ["do_thing"]
// after
MyUser.tasks = [do_thing]  # do_thing is a @task-decorated callable or TaskSet subclass
Defensive patterns

Strategy: type-guard

Validate before calling

from locust.exception import StopUser

def valid_tasks(user_cls) -> bool:
    from locust import TaskSet
    return all(callable(t) or (isinstance(t, type) and issubclass(t, TaskSet)) for t in user_cls.tasks)

Type guard

def is_valid_task(t) -> bool:
    from locust import TaskSet
    return callable(t) or (isinstance(t, type) and issubclass(t, TaskSet))

Try / catch

try:
    env.assign_equal_weights()
except ValueError as e:
    if "Unrecognized task type" in str(e):
        raise RuntimeError("Fix tasks list: use @task callables or TaskSet subclasses") from e
    raise

Prevention

When it happens

Trigger: Putting a non-callable, non-TaskHolder object in a user's `tasks` list, e.g. a class instance, string, or a plain attribute reference that isn't a function.

Common situations: Appending tasks programmatically and pushing the wrong object; typos like `tasks = [my_task()]` (instance instead of function); mixing old-style task tuples incorrectly.

Related errors


AI-assisted analysis of locustio/locust@f391a716e1 (2026-08-29). Data as JSON: /api/errors/047bc94728871f1c. Report an issue: GitHub.