MSYS path conversion breaking Windows terminal commands
NousResearch/hermes-agent · cluster 56147 · environments
Data as of
Nothing open on GitHub. Fix merged in #57006. Check it covers your case.
The short answer
- Known?
- Yes. 6 related items grouped here, 2 issues already closed.
- Fix event
- A fix was merged to main in PR #57006. Check it covers your case. No release data is tracked.
- Tracker
- The maintainers' tracker marks this
partially resolved, deciding PR #57006. That is separate from the fix event. - Still open
- Nothing open on GitHub.
These issues and pull requests address MSYS/Git Bash argv path conversion mangling arguments like '/c' before they reach native Windows commands such as cmd.exe. Proposed fixes involve disabling or excluding MSYS path conversion for affected subprocesses on Windows.
Open issues0
Open PRs0
Fixes on record
-
#57006 fix(terminal): disable MSYS argv path conversion for Windows bash subprocesses
files:
tests/tools/test_local_env_windows_msys.py,tools/environments/local.pyShow the diff
-
tests/tools/test_local_env_windows_msys.py@@ -24,9 +24,12 @@ from tools.environments import local as local_mod from tools.environments.local import ( LocalEnvironment, + _make_run_env, _msys_to_windows_path, _resolve_safe_cwd, + _sanitize_subprocess_env, _windows_to_msys_path, + hermes_subprocess_env, ) @@ -228,6 +231,53 @@ def test_valid_msys_marker_normalized_to_native(self, monkeypatch, tmp_path): assert env.cwd == str(new_dir) +# --------------------------------------------------------------------------- +# MSYS_NO_PATHCONV — native Windows command flags (#56700) +# --------------------------------------------------------------------------- + +class TestWindowsMsysPathconvDefaults: + def test_make_run_env_sets_msys_no_pathconv_on_windows(self, monkeypatch): + monkeypatch.setattr(local_mod, "_IS_WINDOWS", True) + run_env = _make_run_env({}) + assert run_env.get("MSYS_NO_PATHCONV") == "1" + + def test_sanitize_subprocess_env_sets_msys_no_pathconv_on_windows(self, monkeypatch): + monkeypatch.setattr(local_mod, "_IS_WINDOWS", True) + env = _sanitize_subprocess_env({}) + assert env.get("MSYS_NO_PATHCONV") == "1" + + def test_hermes_subprocess_env_sets_msys_no_pathconv_on_windows(self, monkeypatch): + monkeypatch.setattr(local_mod, "_IS_WINDOWS", True) + env = hermes_subprocess_env() + assert env.get("MSYS_NO_PATHCONV") == "1" + + def test_no_pathconv_not_set_on_posix(self, monkeypatch): + monkeypatch.setattr(local_mod, "_IS_WINDOWS", False) + assert "MSYS_NO_PATHCONV" not in _make_run_env({}) + + def test_respects_user_override(self, monkeypatch): + monkeypatch.setattr(local_mod, "_IS_WINDOWS", True) + run_env = _make_run_env({"MSYS_NO_PATHCONV": "0"}) + assert run_env.get("MSYS_NO_PATHCONV") == "0" + + def test_msys2_arg_conv_excl_set_on_windows(self, monkeypatch): + # MSYS2-proper / Cygwin bash ignore MSYS_NO_PATHCONV; they honor + # MSYS2_ARG_CONV_EXCL. Both must be set on every env builder. + monkeypatch.setattr(local_mod, "_IS_WINDOWS", True) + assert _make_run_env({}).get("MSYS2_ARG_CONV_EXCL") == "*" + assert _sanitize_subprocess_env({}).get("MSYS2_ARG_CONV_EXCL") == "*" + assert hermes_subprocess_env().get("MSYS2_ARG_CONV_EXCL") == "*" + + def test_msys2_arg_conv_excl_not_set_on_posix(self, monkeypatch): + monkeypatch.setattr(local_mod, "_IS_WINDOWS", False) + assert "MSYS2_ARG_CONV_EXCL" not in _make_run_env({}) + + def test_msys2_arg_conv_excl_respects_user_override(self, monkeypatch): + monkeypatch.setattr(local_mod, "_IS_WINDOWS", True) + run_env = _make_run_env({"MSYS2_ARG_CONV_EXCL": "/custom"}) + assert run_env.get("MSYS2_ARG_CONV_EXCL") == "/custom" + + # --------------------------------------------------------------------------- # Command wrapping — native Windows cwd must be Git Bash-friendly for cd # --------------------------------------------------------------------------- -
tools/environments/local.py@@ -383,6 +383,8 @@ def _sanitize_subprocess_env(base_env: dict | None, extra_env: dict | None = Non for _marker in _ACTIVE_VENV_MARKER_VARS: sanitized.pop(_marker, None) + _apply_windows_msys_bash_env_defaults(sanitized) + return sanitized @@ -493,6 +495,8 @@ def hermes_subprocess_env(*, inherit_credentials: bool = False) -> dict[str, str for _marker in _ACTIVE_VENV_MARKER_VARS: env.pop(_marker, None) + _apply_windows_msys_bash_env_defaults(env) + # Cross-session leak guard, same as the terminal spawn paths: this helper # copies os.environ, whose HERMES_SESSION_* mirror is a last-writer-wins # global under a concurrent multi-session host. A caller that re-binds the @@ -746,6 +750,29 @@ def _append_missing_sane_path_entries(existing_path: str) -> str: return ":".join(ordered_entries) +def _apply_windows_msys_bash_env_defaults(env: dict) -> None: + """Disable MSYS argument path conversion for Git Bash subprocesses. + + Git Bash rewrites arguments that look like Unix paths (``/FO``, ``/TN``, + ``/Create``) into ``C:/.../git/FO``-style paths, which breaks native + Windows commands such as ``tasklist``, ``schtasks``, and ``wmic``. Hermes + runs terminal commands through bash on Windows, so set the standard MSYS + opt-out by default. Users who need conversion can override in their env. + Refs #56700. + + ``MSYS_NO_PATHCONV`` is honored by Git for Windows bash only. MSYS2-proper + and Cygwin bash (which ``_find_bash`` can still return via the final + ``shutil.which`` fallback) ignore it and honor ``MSYS2_ARG_CONV_EXCL`` + instead, so set both. ``*`` disables all argv conversion — the semantic + equivalent of ``MSYS_NO_PATHCONV=1``. Also fixes ``cmd /c`` mangling + (#56147). + """ + if not _IS_WINDOWS: + return + env.setdefault("MSYS_NO_PATHCONV", "1") + env.setdefault("MSYS2_ARG_CONV_EXCL", "*") + + def _path_env_key(run_env: dict) -> str | None: """Return the PATH env key to update without altering Windows casing. @@ -804,6 +831,8 @@ def _make_run_env(env: dict) -> dict: for _marker in _ACTIVE_VENV_MARKER_VARS: run_env.pop(_marker, None) + _apply_windows_msys_bash_env_defaults(run_env) + return run_env
-
3 PRs closed without merging
From the close comments: duplicate 1 · superseded by another PR 1 · other 1
-
#56228 fix(env): inject MSYS2_ARG_CONV_EXCL=/c on Windows to prevent cmd /c silent failure · superseded by another PR →
a2d49de,#57006,#56147 -
#56734 fix(terminal): disable MSYS path conversion on Windows · duplicate →
#56705,#56700 -
#56783 fix(terminal): keep cmd /c from being rewritten by MSYS on Windows (#56147) · other →
#56228,#56147
Closed issues · 2
How this cluster was grouped
-
Link evidence (
structural links throughout): every member is connected by structural evidence: shared changed files, or a closing/superseded reference. -
Pairwise link density
0.36: 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 LabAt a glance
- Subsystem
- environments
- Merged PRs
- #57006
- Closed issues
- 2
- Attempts
- 3 PRs closed without merging
- Fix link checked
- 2 Jul 2026