locustio/locust · error · RunnerAlreadyExistsError
Environment.runner already exists ({self.runner})
Error message
Environment.runner already exists ({self.runner}) What it means
Environment allows only one runner per instance. `_create_runner` raises RunnerAlreadyExistsError if `self.runner` is already set before assigning a new runner of the given class (local, master, or worker).
Source
Thrown at locust/env.py:123
self.available_user_tasks = available_user_tasks
"""List of the available Tasks per User Classes to pick from in the Task Picker"""
self.dispatcher_class = dispatcher_class
"""A user dispatcher class that decides how users are spawned, default :class:`UsersDispatcher <locust.dispatch.UsersDispatcher>`"""
self.worker_logs: dict[str, list[str]] = {}
"""Captured logs from all connected workers"""
self._remove_user_classes_with_weight_zero()
self._validate_user_class_name_uniqueness()
self._validate_shape_class_instance()
def _create_runner(
self,
runner_class: type[RunnerType],
*args,
**kwargs,
) -> RunnerType:
if self.runner is not None:
raise RunnerAlreadyExistsError(f"Environment.runner already exists ({self.runner})")
self.runner = runner_class(self, *args, **kwargs)
# Attach the runner to the shape class so that the shape class can access user count state
if self.shape_class:
self.shape_class.runner = self.runner
return self.runner
def create_local_runner(self) -> LocalRunner:
"""
Create a :class:`LocalRunner <locust.runners.LocalRunner>` instance for this Environment
"""
return self._create_runner(LocalRunner)
def create_master_runner(self, master_bind_host="*", master_bind_port=5557) -> MasterRunner:
"""
Create a :class:`MasterRunner <locust.runners.MasterRunner>` instance for this Environment
View on GitHub (pinned to f391a716e1)
Solutions
- Create a fresh Environment for each runner you need
- Guard with `if environment.runner is None:` before calling create_*_runner
- Call `environment.runner.stop()` / discard the old Environment instead of re-creating the runner
- In tests, move Environment construction into a pytest fixture with function scope
Example fix
// before
env.create_local_runner()
env.create_local_runner() # raises
// after
if env.runner is None:
env.create_local_runner() Defensive patterns
Strategy: validation
Validate before calling
if env.runner is None:
env.create_local_runner()
else:
env.runner.stop() # or create a new Environment Type guard
def runner_is_free(env) -> bool:
return env.runner is None Try / catch
from locust.exception import RunnerAlreadyExistsError
try:
env.create_local_runner()
except RunnerAlreadyExistsError:
env.runner.stop()
env.runner = None
env.create_local_runner() Prevention
- One Environment per run; build fresh instances in test fixtures
- Check `env.runner is None` before create_*_runner
- Stop and discard runners on teardown
When it happens
Trigger: Calling create_local_runner() twice on the same Environment; calling create_local_runner() after create_master_runner(); reusing a cached Environment object across test launches.
Common situations: Test harnesses that build one Environment fixture and start multiple runs; scripts that retry runner creation after a failed start without discarding the Environment; framework code that initializes a runner automatically then user code calls create_*_runner again.
Related errors
- Tried to set status on a request that has not yet been made.
- wait is True but the amount of users to add is greater than
AI-assisted analysis of locustio/locust@f391a716e1 (2026-08-29).
Data as JSON: /api/errors/087b2794a4d089af.
Report an issue: GitHub.