Docker container env vars silently ignored in config
Cluster 2878 · environments. Data as of
1 open item. Fix merged in #22852 on 10 May 2026. Check it covers your case.
The short answer
- Known?
- Yes. 15 related items grouped here, 5 issues already closed.
- Fix event
- A fix was merged to main in PR #22852. Check it covers your case. No release data is tracked.
- Tracker
- The maintainers' tracker marks this
partially resolved, deciding PR #22852. That is separate from the fix event. - Still open
- 0 issues and 1 PR.
Multiple reports and proposed fixes around docker_forward_env and docker_env config keys being dropped or never forwarded when creating Docker sandbox containers. The members describe the same bug from several angles along with various fix attempts.
Open issues0
Open PRs1
- PR#12825fix(docker): forward configured environment variables to sandbox containers
Fixes on record
-
#14235 fix(terminal): forward docker_forward_env and docker_env to container_config (salvage #10162)
-
#22852 fix(terminal): bridge docker_env config to TERMINAL_DOCKER_ENV (salvage #22626)
files:
cli.py,gateway/run.py,hermes_cli/config.py,tests/tools/test_terminal_config_env_sync.py,tools/terminal_tool.pyShow the diff
-
cli.py@@ -517,6 +517,7 @@ def load_cli_config() -> Dict[str, Any]: "container_disk": "TERMINAL_CONTAINER_DISK", "container_persistent": "TERMINAL_CONTAINER_PERSISTENT", "docker_volumes": "TERMINAL_DOCKER_VOLUMES", + "docker_env": "TERMINAL_DOCKER_ENV", "docker_mount_cwd_to_workspace": "TERMINAL_DOCKER_MOUNT_CWD_TO_WORKSPACE", "docker_run_as_host_user": "TERMINAL_DOCKER_RUN_AS_HOST_USER", "sandbox_dir": "TERMINAL_SANDBOX_DIR", @@ -540,7 +541,7 @@ def load_cli_config() -> Dict[str, Any]: continue if _file_has_terminal_config or env_var not in os.environ: val = terminal_config[config_key] - if isinstance(val, list): + if isinstance(val, (list, dict)): os.environ[env_var] = json.dumps(val) else: os.environ[env_var] = str(val) -
gateway/run.py@@ -460,6 +460,7 @@ def _reload_runtime_env_preserving_config_authority() -> None: "container_disk": "TERMINAL_CONTAINER_DISK", "container_persistent": "TERMINAL_CONTAINER_PERSISTENT", "docker_volumes": "TERMINAL_DOCKER_VOLUMES", + "docker_env": "TERMINAL_DOCKER_ENV", "docker_mount_cwd_to_workspace": "TERMINAL_DOCKER_MOUNT_CWD_TO_WORKSPACE", "docker_run_as_host_user": "TERMINAL_DOCKER_RUN_AS_HOST_USER", "sandbox_dir": "TERMINAL_SANDBOX_DIR", @@ -478,7 +479,7 @@ def _reload_runtime_env_preserving_config_authority() -> None: # receives a literal "~/" which the kernel rejects. if _cfg_key == "cwd" and isinstance(_val, str): _val = os.path.expanduser(_val) - if isinstance(_val, list): + if isinstance(_val, (list, dict)): os.environ[_env_var] = json.dumps(_val) else: os.environ[_env_var] = str(_val) -
hermes_cli/config.py@@ -4843,6 +4843,7 @@ def set_config_value(key: str, value: str): "terminal.vercel_runtime": "TERMINAL_VERCEL_RUNTIME", "terminal.docker_mount_cwd_to_workspace": "TERMINAL_DOCKER_MOUNT_CWD_TO_WORKSPACE", "terminal.docker_run_as_host_user": "TERMINAL_DOCKER_RUN_AS_HOST_USER", + "terminal.docker_env": "TERMINAL_DOCKER_ENV", # terminal.cwd intentionally excluded — CLI resolves at runtime, # gateway bridges it in gateway/run.py. Persisting to .env causes # stale values to poison child processes. -
tests/tools/test_terminal_config_env_sync.py@@ -208,3 +208,19 @@ def test_docker_mount_cwd_to_workspace_is_bridged_everywhere(): assert "docker_mount_cwd_to_workspace" in _gateway_env_map_keys() assert "docker_mount_cwd_to_workspace" in _save_config_env_sync_keys() assert "TERMINAL_DOCKER_MOUNT_CWD_TO_WORKSPACE" in _terminal_tool_env_var_names() + + +def test_docker_env_is_bridged_everywhere(): + """Regression pin for docker_env config key being silently ignored. + + ``terminal.docker_env`` in config.yaml specifies extra env vars to inject + into the Docker container at runtime. The key was present in + _create_environment's container_config consumer (line ~1130) but never + bridged from config.yaml to TERMINAL_DOCKER_ENV, so the dict was always + empty regardless of what the user set. Guard all four bridging points so + this cannot regress. + """ + assert "docker_env" in _cli_env_map_keys() + assert "docker_env" in _gateway_env_map_keys() + assert "docker_env" in _save_config_env_sync_keys() + assert "TERMINAL_DOCKER_ENV" in _terminal_tool_env_var_names() -
tools/terminal_tool.py@@ -1085,6 +1085,7 @@ def _get_env_config() -> Dict[str, Any]: "container_disk": _parse_env_var("TERMINAL_CONTAINER_DISK", "51200"), # MB (default 50GB) "container_persistent": os.getenv("TERMINAL_CONTAINER_PERSISTENT", "true").lower() in ("true", "1", "yes"), "docker_volumes": _parse_env_var("TERMINAL_DOCKER_VOLUMES", "[]", json.loads, "valid JSON"), + "docker_env": _parse_env_var("TERMINAL_DOCKER_ENV", "{}", json.loads, "valid JSON"), "docker_run_as_host_user": os.getenv("TERMINAL_DOCKER_RUN_AS_HOST_USER", "false").lower() in ("true", "1", "yes"), }
-
7 PRs closed without merging
From the close comments: done elsewhere 3 · merged via another change 2 · stale or abandoned 1 · other 1
- #2879 fix(docker): include docker_forward_env in container_config dict · stale or abandoned
- #2881 fix(docker): include docker_forward_env in container_config dict · done elsewhere
-
#4917 fix(terminal): pass docker_forward_env through terminal tool · done elsewhere →
db86ed1,#4916 -
#4972 fix: include docker_forward_env in terminal_tool container_config · merged via another change →
db86ed1,#4916 - #17620 fix(execute_code): forward docker_forward_env into container_config · done elsewhere
Closed issues · 5
- Closed#2878fix(docker): docker_forward_env config key silently ignored — missing from container_config dict
- Closed#4916[Bug]: terminal_tool drops docker_forward_env when creating container sandboxes
- Closed#5722terminal.docker_forward_env and terminal.docker_env are silently ignored from config.yaml
- Closed#12534Docker sandbox never receives env vars from docker_forward_env: missing keys in container_config
- Closed#20537Bug: docker_env configuration is completely ignored (env_mappings missing docker_env)
How this cluster was grouped
-
Link evidence (
partly structural links): some members are connected by structural evidence (shared changed files, or a closing/superseded reference); the rest are joined by an automated relevance judgement over their text. - Members outside that structural core may belong to a different underlying problem.
-
Pairwise link density
0.11: the share of item pairs that carry a link, counting a structural link in full and a relevance-only link at 0.36.1.00means every pair is linked.
Pick up a Lab task
Check whether a fix covers the open issues here, with your own agent. Bring back evidence for maintainers.
Open the Lab