{"record":{"id":"55eeeea1a277e809","repo":"SeleniumHQ/selenium","slug":"env-must-be-a-mapping-of-environment-variables","errorCode":null,"errorMessage":"env must be a mapping of environment variables","messagePattern":"env must be a mapping of environment variables","errorType":"validation","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"py/selenium/webdriver/remote/server.py","lineNumber":146,"sourceCode":"    @property\n    def log_level(self):\n        return self._log_level\n\n    @log_level.setter\n    def log_level(self, log_level):\n        levels = (\"SEVERE\", \"WARNING\", \"INFO\", \"CONFIG\", \"FINE\", \"FINER\", \"FINEST\")\n        if log_level not in levels:\n            raise TypeError(f\"log_level must be one of: {', '.join(levels)}\")\n        self._log_level = log_level\n\n    @property\n    def env(self):\n        return self._env\n\n    @env.setter\n    def env(self, env):\n        if env is not None and not isinstance(env, collections.abc.Mapping):\n            raise TypeError(\"env must be a mapping of environment variables\")\n        self._env = env\n\n    @property\n    def java_path(self):\n        return self._java_path\n\n    @java_path.setter\n    def java_path(self, java_path):\n        if java_path and not os.path.exists(java_path):\n            raise OSError(f\"Can't find java executable located at {java_path}\")\n        self._java_path = java_path\n\n    def _wait_for_server(self, timeout=10):\n        start = time.time()\n        while time.time() - start < timeout:\n            try:\n                urllib.request.urlopen(self.status_url)\n                return True","sourceCodeStart":128,"sourceCodeEnd":164,"githubUrl":"https://github.com/SeleniumHQ/selenium/blob/aa36b38e696a0909e973bdf5e2f9031ffe842c4b/py/selenium/webdriver/remote/server.py#L128-L164","documentation":"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.","triggerScenarios":"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.","commonSituations":"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).","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."],"exampleFix":"# before\nserver.env = ['DISPLAY=:0', 'JAVA_OPTS=-Xmx2g']\n\n# after\nserver.env = {'DISPLAY': ':0', 'JAVA_OPTS': '-Xmx2g'}","handlingStrategy":"type-guard","validationCode":"import collections.abc\nif env is not None and not isinstance(env, collections.abc.Mapping):\n    raise TypeError('env must be a Mapping of name->value')\nserver.env = env","typeGuard":"def is_env_mapping(env) -> bool:\n    return env is None or isinstance(env, collections.abc.Mapping)","tryCatchPattern":null,"preventionTips":["Keep environment as a dict in your config layer; only coerce at the boundary.","Prefer os.environ | {'EXTRA': 'x'} (dict merge) over list builders."],"tags":["configuration","validation","type-error","server-runner"],"backgroundTag":null,"analyzedSha":"aa36b38e696a0909e973bdf5e2f9031ffe842c4b","analyzedAt":"2026-08-14T02:32:32.244Z","schemaVersion":2},"datasetVersion":"2026-08-14T05:17:29.042Z"}