fix(exec): respect PATH order for virtualenv resolution in mise x#8342
fix(exec): respect PATH order for virtualenv resolution in mise x#8342
Conversation
Remove the `which_bin` pre-resolution that was introduced in #8276 to prevent wrapper script recursion. This pre-resolution bypasses PATH entirely for mise-managed tools, breaking `_.python.venv` and similar configs where a virtualenv binary should take precedence over the mise-managed install. The shim stripping in `exec_program` (also from #8276) already prevents the main recursion vector (shims in PATH). The wrapper script edge case should not be solved by bypassing PATH for all programs. Fixes #8340 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Summary of ChangesHello @jdx, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed! This pull request resolves a regression where Highlights
Changelog
Activity
Using Gemini Code AssistThe full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips. Invoking Gemini You can request assistance from Gemini at any point by creating a comment using either
Customization To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a Limitations & Feedback Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here. You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension. Footnotes
|
Regression test that verifies `mise x -- tool` respects PATH order when a virtualenv-like directory is prepended via mise config. Fails without the accompanying fix due to `which_bin` pre-resolution bypassing PATH. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
There was a problem hiding this comment.
Code Review
This pull request addresses an issue where mise x would not respect the PATH order for virtualenv resolution. The change removes a block of code responsible for pre-resolving program paths, which was causing this issue by bypassing the standard PATH lookup. The original purpose of the removed code, preventing shim recursion, is now handled by a different mechanism that remains in place. The change is correct and well-justified, fixing the described bug without reintroducing the recursion problem.
Greptile SummaryThis PR removes the Key changes:
Rationale: Confidence Score: 4/5
Important Files Changed
Flowchart%%{init: {'theme': 'neutral'}}%%
flowchart TD
Start["`mise x -- python`"] --> ParseCmd["Parse command"]
ParseCmd --> BuildEnv["Build env with PATH<br/>(includes .venv/bin if configured)"]
BuildEnv --> ExecProg["exec_program(program, args, env)"]
ExecProg --> CheckPath{Is program<br/>already a path?}
CheckPath -->|Yes, contains /| UseAsIs["Use as-is"]
CheckPath -->|No, bare name| StripShims["Strip shims from PATH"]
StripShims --> WhichIn["which_in(program, filtered_path)"]
WhichIn --> Found{Found?}
Found -->|Yes| ResolvedPath["Use resolved path<br/>(e.g., .venv/bin/python)"]
Found -->|No| Fallback["Fall back to original"]
UseAsIs --> Exec["execvp()"]
ResolvedPath --> Exec
Fallback --> Exec
style StripShims fill:#90EE90
style WhichIn fill:#87CEEB
style ResolvedPath fill:#FFD700
Last reviewed commit: d85ede1 |
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
Bugbot Autofix is OFF. To automatically fix reported issues with Cloud Agents, enable Autofix in the Cursor dashboard.
Hyperfine Performance
|
| Command | Mean [ms] | Min [ms] | Max [ms] | Relative |
|---|---|---|---|---|
mise-2026.2.20 x -- echo |
26.3 ± 0.9 | 24.3 | 32.9 | 1.00 |
mise x -- echo |
26.7 ± 1.0 | 23.9 | 29.6 | 1.01 ± 0.05 |
mise env
| Command | Mean [ms] | Min [ms] | Max [ms] | Relative |
|---|---|---|---|---|
mise-2026.2.20 env |
25.3 ± 0.9 | 23.2 | 29.6 | 1.00 |
mise env |
25.6 ± 0.9 | 23.3 | 28.7 | 1.01 ± 0.05 |
mise hook-env
| Command | Mean [ms] | Min [ms] | Max [ms] | Relative |
|---|---|---|---|---|
mise-2026.2.20 hook-env |
25.2 ± 0.8 | 23.3 | 28.3 | 1.00 |
mise hook-env |
26.6 ± 1.1 | 24.1 | 31.1 | 1.05 ± 0.05 |
mise ls
| Command | Mean [ms] | Min [ms] | Max [ms] | Relative |
|---|---|---|---|---|
mise-2026.2.20 ls |
23.5 ± 0.9 | 21.4 | 28.4 | 1.00 |
mise ls |
24.6 ± 1.0 | 21.6 | 29.0 | 1.05 ± 0.06 |
xtasks/test/perf
| Command | mise-2026.2.20 | mise | Variance |
|---|---|---|---|
| install (cached) | 154ms | 154ms | +0% |
| ls (cached) | 85ms | 86ms | -1% |
| bin-paths (cached) | 90ms | 90ms | +0% |
| task-ls (cached) | 827ms | 832ms | +0% |
Addresses Cursor Bugbot feedback on PR #8342. Simulates the .devcontainer/bin/tool scenario from #8276 where a wrapper script that calls `mise x -- tool` sits before mise tool paths in the system PATH. The test passes because `exec_program` resolves programs via the mise-computed PATH (where tool install paths are prepended before the original system PATH), so the real binary is found before the wrapper. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Greptile SummaryReverts the
Confidence Score: 5/5
Important Files Changed
Flowchart%%{init: {'theme': 'neutral'}}%%
flowchart TD
A[User runs: mise x -- python] --> B[Exec::run parses command]
B --> C[Build toolset with mise config]
C --> D[Install missing tools if needed]
D --> E[Compute env_with_path]
E --> F{PATH construction}
F --> G[Prepend mise tool paths]
G --> H[Add _.path entries like .venv/bin]
H --> I[Add original PATH]
I --> J[exec_program called with bare 'python']
J --> K{Is program already absolute path?}
K -->|Yes| L[Use as-is]
K -->|No| M[Filter shims from PATH]
M --> N[Use which_in to resolve]
N --> O{Which binary found first?}
O -->|.venv/bin/python| P[Execute venv python]
O -->|mise python| Q[Execute mise python]
O -->|wrapper script| R[Wrapper calls mise x again]
R --> S[Recursive call prepends mise paths again]
S --> T[Mise python found before wrapper]
T --> Q
Last reviewed commit: b241665 |
### 🐛 Bug Fixes - **(exec)** respect PATH order for virtualenv resolution in mise x by @jdx in [#8342](#8342) - **(task)** revert process group changes that cause hangs with nested mise tasks by @jdx in [#8347](#8347) - **(task)** resolve vars from subdirectory configs for monorepo tasks by @jdx in [#8343](#8343) - **(task)** resolve dependencies before prepare to fix monorepo glob deps by @jdx in [#8353](#8353) - python noarch with Conda backend by @wolfv in [#8349](#8349) ### New Contributors - @wolfv made their first contribution in [#8349](#8349) ## 📦 Aqua Registry Updates #### New Packages (3) - [`alexhallam/tv`](https://github.com/alexhallam/tv) - [`arcanist-sh/hx`](https://github.com/arcanist-sh/hx) - [`dathere/qsv`](https://github.com/dathere/qsv) #### Updated Packages (3) - [`astral-sh/ruff`](https://github.com/astral-sh/ruff) - [`caarlos0/fork-cleaner`](https://github.com/caarlos0/fork-cleaner) - [`rhysd/actionlint`](https://github.com/rhysd/actionlint)
…x#8342) ## Summary - Remove the `ts.which_bin()` pre-resolution from `Exec::run()` that was introduced in jdx#8276 - This pre-resolution bypassed PATH entirely for mise-managed tools, breaking `_.python.venv` and similar configs where a virtualenv binary should take precedence over the mise-managed install - The shim stripping in `exec_program` (also from jdx#8276) already prevents shim recursion, which was the primary problem that PR solved ## Root Cause PR jdx#8276 added two fixes for infinite recursion: 1. Strip shims from PATH in `exec_program` — prevents shim recursion (**kept**) 2. Pre-resolve bare program names via `which_bin` — prevents wrapper script recursion (**removed**) Fix #2 resolves e.g. `python` → `~/.local/share/mise/installs/python/3.9.1/bin/python` before PATH is computed. Since the result is an absolute path, `exec_program` skips PATH lookup entirely, so `.venv/bin/python` (added by `_.python.venv`) is never found. Fixes jdx#8340 ## Test plan - [x] `cargo check` — no warnings - [x] `mise run test:e2e test_exec` — all exec e2e tests pass - [x] `test_exec_shim_recursion` still passes (shim stripping in `exec_program` handles this) 🤖 Generated with [Claude Code](https://claude.com/claude-code) <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Medium Risk** > Changes how `mise x` resolves executables, which can alter which binary runs in edge PATH setups. Added E2E tests reduce regression risk, but behavior changes could impact users relying on the old forced mise-path resolution. > > **Overview** > `mise x` no longer pre-resolves bare command names to a mise-managed tool path via `Toolset::which_bin` in `Exec::run`, allowing normal PATH lookup to pick up higher-precedence overrides like virtualenv binaries. > > Adds two E2E regression tests: one ensuring PATH-prepended “venv” bins win over mise installs during `mise x`, and another ensuring a PATH-preceding wrapper that re-invokes `mise x` doesn’t hang (infinite recursion) and still executes the real tool. > > <sup>Written by [Cursor Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit b241665. This will update automatically on new commits. Configure [here](https://cursor.com/dashboard?tab=bugbot).</sup> <!-- /CURSOR_SUMMARY --> --------- Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
### 🐛 Bug Fixes - **(exec)** respect PATH order for virtualenv resolution in mise x by @jdx in [jdx#8342](jdx#8342) - **(task)** revert process group changes that cause hangs with nested mise tasks by @jdx in [jdx#8347](jdx#8347) - **(task)** resolve vars from subdirectory configs for monorepo tasks by @jdx in [jdx#8343](jdx#8343) - **(task)** resolve dependencies before prepare to fix monorepo glob deps by @jdx in [jdx#8353](jdx#8353) - python noarch with Conda backend by @wolfv in [jdx#8349](jdx#8349) ### New Contributors - @wolfv made their first contribution in [jdx#8349](jdx#8349) ## 📦 Aqua Registry Updates #### New Packages (3) - [`alexhallam/tv`](https://github.com/alexhallam/tv) - [`arcanist-sh/hx`](https://github.com/arcanist-sh/hx) - [`dathere/qsv`](https://github.com/dathere/qsv) #### Updated Packages (3) - [`astral-sh/ruff`](https://github.com/astral-sh/ruff) - [`caarlos0/fork-cleaner`](https://github.com/caarlos0/fork-cleaner) - [`rhysd/actionlint`](https://github.com/rhysd/actionlint)
Summary
ts.which_bin()pre-resolution fromExec::run()that was introduced in fix(exec): strip shims from PATH on Unix to prevent infinite recursion #8276_.python.venvand similar configs where a virtualenv binary should take precedence over the mise-managed installexec_program(also from fix(exec): strip shims from PATH on Unix to prevent infinite recursion #8276) already prevents shim recursion, which was the primary problem that PR solvedRoot Cause
PR #8276 added two fixes for infinite recursion:
exec_program— prevents shim recursion (kept)which_bin— prevents wrapper script recursion (removed)Fix #2 resolves e.g.
python→~/.local/share/mise/installs/python/3.9.1/bin/pythonbefore PATH is computed. Since the result is an absolute path,exec_programskips PATH lookup entirely, so.venv/bin/python(added by_.python.venv) is never found.Fixes #8340
Test plan
cargo check— no warningsmise run test:e2e test_exec— all exec e2e tests passtest_exec_shim_recursionstill passes (shim stripping inexec_programhandles this)🤖 Generated with Claude Code
Note
Medium Risk
Changes how
mise xresolves executables, which can alter which binary runs in edge PATH setups. Added E2E tests reduce regression risk, but behavior changes could impact users relying on the old forced mise-path resolution.Overview
mise xno longer pre-resolves bare command names to a mise-managed tool path viaToolset::which_bininExec::run, allowing normal PATH lookup to pick up higher-precedence overrides like virtualenv binaries.Adds two E2E regression tests: one ensuring PATH-prepended “venv” bins win over mise installs during
mise x, and another ensuring a PATH-preceding wrapper that re-invokesmise xdoesn’t hang (infinite recursion) and still executes the real tool.Written by Cursor Bugbot for commit b241665. This will update automatically on new commits. Configure here.