Skip to content

fix(env): drop stale mise install dirs from mise x/run child PATH#10422

Merged
jdx merged 1 commit into
jdx:mainfrom
JamBalaya56562:fix-exec-stale-install-path
Jun 14, 2026
Merged

fix(env): drop stale mise install dirs from mise x/run child PATH#10422
jdx merged 1 commit into
jdx:mainfrom
JamBalaya56562:fix-exec-stale-install-path

Conversation

@JamBalaya56562

@JamBalaya56562 JamBalaya56562 commented Jun 14, 2026

Copy link
Copy Markdown
Contributor

What

mise x tool@X / run / env correctly remap the direct command, but a stale mise-managed install dir left earlier on PATH — e.g. carried in from a frozen env snapshot of a previously activated shell (IDE terminals, CI wrappers, AI-agent harnesses) — stayed ahead of the bin dir mise injects. So PATH lookups inside the process tree (subshells, #!/usr/bin/env shebangs, package managers spawning workers) still resolved the other version: a split-brain where node --version says 22 while the tests actually run on 24.

Reported in #10345 (repro with two node versions).

Fix

When Toolset composes the child environment, filter mise-managed install dirs out of the inherited PATH (mise re-adds the current toolset's bin dirs, so the requested version wins for the whole process tree). Mirrors the hook-env reactivation fix (#10162): its is_mise_install_path helper is moved to path_env, shared, and extended to also cover shared/system install dirs (MISE_SHARED_INSTALL_DIRS + the system installs dir) that find_in_shared_installs resolves into. The install-dir list is computed once per PATH-composition pass to keep the per-entry check cheap (hook-env runs on every prompt).

Tests

  • e2e/cli/test_exec_stale_install_path: with installs/dummy/2.0.0/bin prepended to PATH, mise x dummy@1.0.0 -- sh -c 'command -v dummy' resolves into installs/dummy/1.0.0, not the stale 2.0.0 dir.

Addresses discussion #10345.

🤖 Generated with Claude Code

Summary by CodeRabbit

  • Bug Fixes

    • Fixed version resolution when stale mise-managed install directories are left on PATH, ensuring mise x selects the requested version instead of being influenced by older remnants.
    • Updated PATH handling to exclude mise-managed install directory entries when building the effective environment, preventing incorrect PATH ordering.
  • Tests

    • Added an end-to-end regression test covering stale install-path behavior and verifying correct resolution in both direct and child-process commands.

@coderabbitai

coderabbitai Bot commented Jun 14, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: f08f45e6-cfb3-49c4-bdfe-bd1c669af9bb

📥 Commits

Reviewing files that changed from the base of the PR and between 1b2bcd8 and c9a30a5.

📒 Files selected for processing (4)
  • e2e/cli/test_exec_stale_install_path
  • src/cli/hook_env.rs
  • src/path_env.rs
  • src/toolset/toolset_env.rs
🚧 Files skipped from review as they are similar to previous changes (4)
  • e2e/cli/test_exec_stale_install_path
  • src/path_env.rs
  • src/cli/hook_env.rs
  • src/toolset/toolset_env.rs

📝 Walkthrough

Walkthrough

Centralizes install-path detection into path_env.rs, filters stale install dirs from env::PATH across all PATH construction sites in toolset_env.rs, refactors hook_env.rs to use shared helpers, and adds a regression test validating the fix.

Changes

Stale install dir PATH fix

Layer / File(s) Summary
Centralized install-dir detection helpers
src/path_env.rs
Adds mise_install_dirs() returning all mise-managed install directories and is_mise_install_path() classifying a path via prefix matching with canonicalization fallback.
hook_env.rs refactored to shared helpers
src/cli/hook_env.rs
Removes the local is_mise_install_path helper, cleans up imports, and updates build_path_operations to precompute mise_install_dirs once and delegate to crate::path_env.
Stale dirs filtered at all PATH construction sites
src/toolset/toolset_env.rs
Adds pristine_path_without_install_dirs() that strips mise install dir entries from env::PATH; substitutes it for raw env::PATH in env_with_path_without_tools, env_with_path, env_with_path_and_split, try_load_env_cache, and final_env.
E2E regression test
e2e/cli/test_exec_stale_install_path
New bash test simulating a frozen-shell stale-PATH scenario, asserting mise x dummy@1.0.0 resolves to 1.0.0 both directly and in a spawned child process.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

  • jdx/mise#10162: Addresses the same stale-entry detection logic in src/cli/hook_env.rs for PATH ordering; this PR directly builds on that work by extracting that detection into src/path_env.rs and applying it to toolset_env.rs.

Poem

🐇 Hoppity-hop down the PATH I go,
Old stale bins piled high like snow.
But now I sweep with pristine_path,
No ghost of 2.0.0 blocks my math.
The right dummy answers my call —
1.0.0 wins, stale dirs fall! 🎉

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately describes the main change: filtering stale mise install directories from the PATH in mise x/run child processes to ensure correct tool version resolution.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.


Comment @coderabbitai help to get the list of available commands and usage tips.

@greptile-apps

greptile-apps Bot commented Jun 14, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR fixes a split-brain version resolution issue where a stale mise-managed install dir carried in via a frozen env snapshot (IDE terminal, CI wrapper) stayed ahead of the bin dir mise x/run/env injects, causing subshells and shebangs inside the process tree to see the wrong version.

  • Core fix: Introduces pristine_path_without_install_dirs() in toolset_env.rs that strips all mise-managed install dirs (primary + shared/system) from the inherited PATH before the current toolset's bin dirs are prepended. All six PATH-building sites are updated consistently.
  • Shared helper: is_mise_install_path is moved from hook_env.rs into path_env.rs and extended to also cover MISE_SHARED_INSTALL_DIRS and the system installs dir.
  • Regression test: e2e/cli/test_exec_stale_install_path prepends the 2.0.0 bin dir to PATH and asserts that command -v dummy inside a child shell resolves to the 1.0.0 install dir.

Confidence Score: 5/5

Safe to merge — the change is narrowly scoped to filtering mise-managed dirs before PATH construction and all existing PATH-building paths are updated consistently.

Every PATH-building site in toolset_env.rs (cached and non-cached) now strips stale install dirs before adding the current toolset bins. The shared helper is a clean extraction with broader coverage, and the regression test directly exercises the broken child-process PATH lookup.

No files require special attention.

Important Files Changed

Filename Overview
src/path_env.rs Adds mise_install_dirs() and is_mise_install_path() helpers, refactored out of hook_env.rs and extended to cover shared/system install dirs. Logic is correct: literal prefix check first, then canonicalized fallback.
src/toolset/toolset_env.rs All six PATH-building sites (cached and non-cached paths) are updated to start from pristine_path_without_install_dirs(), ensuring stale install dirs are stripped before the current toolset's bins are re-added.
src/cli/hook_env.rs Removes the private is_mise_install_path and delegates to the new shared helper in path_env, passing the pre-computed mise_install_dirs list.
e2e/cli/test_exec_stale_install_path New regression test prepends a stale 2.0.0 bin dir to PATH, then asserts both the direct command and a command -v inside a child shell resolve to 1.0.0.

Reviews (2): Last reviewed commit: "fix(env): drop stale mise install dirs f..." | Re-trigger Greptile

Comment thread src/toolset/toolset_env.rs
`mise x tool@X` / `run` / `env` correctly remap the direct command, but a stale
mise-managed install dir left earlier on PATH (e.g. from a frozen env snapshot of
a previously activated shell) stayed ahead of the bin dir mise injects, so PATH
lookups inside the process tree (subshells, env shebangs, package-manager workers)
still resolved the other version -- a split-brain where `node --version` says 22
while the tests actually run on 24.

Filter mise-managed install dirs out of the inherited PATH when Toolset composes
the child env, so the requested version wins for the whole process tree. Mirrors
the hook-env reactivation fix (jdx#10162): share its is_mise_install_path helper
(moved to path_env) and extend it to also cover shared/system install dirs
(MISE_SHARED_INSTALL_DIRS + the system installs dir) that find_in_shared_installs
resolves into.

Addresses discussion jdx#10345.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@JamBalaya56562 JamBalaya56562 force-pushed the fix-exec-stale-install-path branch from 1b2bcd8 to c9a30a5 Compare June 14, 2026 09:16
@jdx jdx merged commit 0d62eec into jdx:main Jun 14, 2026
33 checks passed
@JamBalaya56562 JamBalaya56562 deleted the fix-exec-stale-install-path branch June 14, 2026 22:34
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants