SeleniumHQ/selenium · error · TypeError
env must be a mapping of environment variables
Error message
env must be a mapping of environment variables
What it means
Raised by the `env` property setter when the value is not None and is not a `collections.abc.Mapping`. The server runner passes `env` straight into `subprocess.Popen`, which requires a dict-like environment; the guard rejects incompatible types before the process spawn. It is a TypeError signaling incorrect caller usage.
Source
Thrown at py/selenium/webdriver/remote/server.py:146
@property
def log_level(self):
return self._log_level
@log_level.setter
def log_level(self, log_level):
levels = ("SEVERE", "WARNING", "INFO", "CONFIG", "FINE", "FINER", "FINEST")
if log_level not in levels:
raise TypeError(f"log_level must be one of: {', '.join(levels)}")
self._log_level = log_level
@property
def env(self):
return self._env
@env.setter
def env(self, env):
if env is not None and not isinstance(env, collections.abc.Mapping):
raise TypeError("env must be a mapping of environment variables")
self._env = env
@property
def java_path(self):
return self._java_path
@java_path.setter
def java_path(self, java_path):
if java_path and not os.path.exists(java_path):
raise OSError(f"Can't find java executable located at {java_path}")
self._java_path = java_path
def _wait_for_server(self, timeout=10):
start = time.time()
while time.time() - start < timeout:
try:
urllib.request.urlopen(self.status_url)
return TrueView on GitHub (pinned to aa36b38e69)
Solutions
- Pass a dict (or any Mapping) of name->value, e.g. {'JAVA_OPTS': '-Xmx2g'}.
- Convert a list of 'K=V' strings into a dict before assigning: dict(kv.split('=',1) for kv in lst).
- Pass None (or simply don't set it) to inherit the current process environment.
Example fix
# before
server.env = ['DISPLAY=:0', 'JAVA_OPTS=-Xmx2g']
# after
server.env = {'DISPLAY': ':0', 'JAVA_OPTS': '-Xmx2g'} Defensive patterns
Strategy: type-guard
Validate before calling
import collections.abc
if env is not None and not isinstance(env, collections.abc.Mapping):
raise TypeError('env must be a Mapping of name->value')
server.env = env Type guard
def is_env_mapping(env) -> bool:
return env is None or isinstance(env, collections.abc.Mapping) Prevention
- Keep environment as a dict in your config layer; only coerce at the boundary.
- Prefer os.environ | {'EXTRA': 'x'} (dict merge) over list builders.
When it happens
Trigger: Assigning `server.env = ['FOO=bar']` (list of strings, a shell-export style), a tuple, a set, or a plain string. Also assigning a custom object that does not register as a Mapping even if it is dict-like.
Common situations: Translating a shell-style env list (`['A=1','B=2']`) into the env setter. Reusing a JSON-loaded structure that turned out to be a list rather than an object. Passing os.environ is fine (it is a Mapping).
Related errors
- log_level must be one of: {', '.join(levels)}
- Can't find java executable located at {java_path}
- Invalid URL: ${aUrl}
- no capabilities provided for merge
- Capability keys must be strings: ${typeof key}
AI-assisted analysis of SeleniumHQ/selenium@aa36b38e69 (2026-08-14).
Data as JSON: /api/errors/55eeeea1a277e809.
Report an issue: GitHub.