Skip to content

fix(shim): use which_no_shims when resolving mise binary in reshim and doctor#9071

Merged
jdx merged 2 commits intojdx:mainfrom
kevinswiber:fix/reshim-shims-on-path
Apr 15, 2026
Merged

fix(shim): use which_no_shims when resolving mise binary in reshim and doctor#9071
jdx merged 2 commits intojdx:mainfrom
kevinswiber:fix/reshim-shims-on-path

Conversation

@kevinswiber
Copy link
Copy Markdown
Contributor

Summary

When shims are on PATH (standard for non-interactive shells using mise activate --shims), file::which("mise") in both reshim() and analyze_shims() resolves to the mise shim (~/.local/share/mise/shims/mise) instead of the real binary. This causes:

  • reshim: creates shims pointing to the mise shim, including a circular mise → mise symlink, breaking all shims
  • doctor: compares shim symlink targets against the shim path rather than the real binary, falsely reporting all shims as "missing" even immediately after mise reshim

This is triggered when a mise shim exists in the shims directory, which happens when core:rust is in the toolset and mise was installed via cargo install/cargo binstall (the ~/.cargo/bin directory containing the mise binary is scanned as a tool bin directory).

Fix

Use file::which_no_shims("mise") instead of file::which("mise") in both src/shims.rs (reshim) and src/cli/doctor/mod.rs (analyze_shims). The which_no_shims function already exists in the codebase for preventing this exact kind of shim self-reference.

Steps to reproduce

  1. Install mise via cargo (cargo binstall mise or cargo install mise)
  2. Have core:rust (or any tool whose bin dir contains mise) in the toolset
  3. Configure shell for non-interactive shim activation:
    # conf.d/mise.fish
    if status is-interactive
      mise activate fish | source
    else
      mise activate fish --shims | source
    end
  4. Run: fish -c "mise reshim && mise doctor"
  5. Observe: doctor reports all shims as missing, and shims are circular symlinks

Test plan

  • New e2e test test_reshim_with_shims_on_path that simulates a mise shim on PATH, runs reshim, and verifies shims still point to the real binary and doctor reports no issues
  • Test verified to fail on unfixed code and pass on fixed code
  • All existing shim and doctor e2e tests continue to pass (test_shims, test_shims_fallback, test_doctor, test_exec_shim_recursion)

…d doctor

When shims are on PATH (e.g. non-interactive shells using
`mise activate --shims`), `file::which("mise")` finds the mise shim
instead of the real binary. This causes `reshim` to create circular
symlinks (mise shim pointing to itself) and `doctor` to falsely report
all shims as missing.

Use `file::which_no_shims` which already exists for this purpose — it
filters the shims directory from PATH before searching.
@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps Bot commented Apr 13, 2026

Greptile Summary

Fixes a circular-shim bug by replacing file::which("mise") with file::which_no_shims("mise") in both reshim() and analyze_shims(), preventing the mise shim itself from being selected as the target when the shims directory is on PATH. A companion e2e regression test is included, but it is committed with mode 100755; project convention per CLAUDE.md keeps e2e test files non-executable (100644).

Confidence Score: 5/5

Safe to merge — the fix is minimal, targeted, and fully covered by the new regression test; the only finding is a P2 file-permission nit.

Both code changes are single-line, use an existing utility function purpose-built for this scenario, and no other file::which("mise") calls remain in the codebase. All findings are P2 or lower.

e2e/cli/test_reshim_with_shims_on_path — executable bit (100755) should be 100644 per project convention.

Important Files Changed

Filename Overview
src/shims.rs Replaces file::which("mise") with file::which_no_shims("mise") in reshim() to prevent resolving to the mise shim itself when the shims directory is on PATH, fixing the circular-symlink bug.
src/cli/doctor/mod.rs Same one-line fix in analyze_shims(): uses which_no_shims so the doctor compares shim targets against the real binary path rather than the shim itself, eliminating false "shims are missing" reports.
e2e/cli/test_reshim_with_shims_on_path New regression test simulating a mise shim on PATH; correctly verifies shim targets and doctor output, but file is committed as executable (100755) contrary to project convention.

Reviews (2): Last reviewed commit: "[autofix.ci] apply automated fixes" | Re-trigger Greptile

Copy link
Copy Markdown
Contributor

@gemini-code-assist gemini-code-assist Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request prevents the creation of circular symlinks during reshimming by ensuring the real mise binary is identified even when shims are already on the PATH. It updates the reshim and doctor commands to use a new which_no_shims helper and includes a regression test. A review comment suggests absolutizing the mise_bin path in the doctor command to ensure consistency with the reshim implementation and avoid potential false reports of missing shims.

Comment thread src/cli/doctor/mod.rs

async fn analyze_shims(&mut self, config: &Arc<Config>, toolset: &Toolset) {
let mise_bin = file::which("mise").unwrap_or(env::MISE_BIN.clone());
let mise_bin = file::which_no_shims("mise").unwrap_or(env::MISE_BIN.clone());
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

For consistency with the reshim implementation in src/shims.rs, this path should ideally be absolutized.

In src/shims.rs, mise_bin is explicitly absolutized (line 128) before being used to create shims. If doctor uses a different path representation (e.g., a relative path if which_no_shims finds one in PATH), the comparison in shims::get_actual_shims (line 436 in src/shims.rs) might fail when checking if a shim's target matches mise_bin, potentially leading to false "missing shim" reports in the doctor output.

Note that since analyze_shims does not return a Result, you would need to handle the potential error from an .absolutize() call manually or ensure the path is absolute via other means.

@jdx jdx merged commit 97f4b19 into jdx:main Apr 15, 2026
34 checks passed
mise-en-dev added a commit that referenced this pull request Apr 15, 2026
### 🚀 Features

- **(npm)** use --min-release-age for npm 11.10.0+ supply chain
protection by @webkaz in [#9072](#9072)
- **(registry)** add openfga by @mnm364 in
[#9084](#9084)
- **(task)** allow to set confirmation default by @roele in
[#9089](#9089)
- support os/arch compound syntax in tool os filtering by @RobertDeRose
in [#9088](#9088)

### 🐛 Bug Fixes

- **(activate)** export __MISE_EXE and resolve bare ARGV0 to absolute
path by @fru1tworld in [#9081](#9081)
- **(install)** support aliased installs sharing a backend by @jdx in
[#9093](#9093)
- **(shim)** use which_no_shims when resolving mise binary in reshim and
doctor by @kevinswiber in [#9071](#9071)
- filter empty segments in colon-separated env var parsing by @baby-joel
in [#9076](#9076)

### 📚 Documentation

- fix wrong file reference to forgejo backend implemenation by @roele in
[#9090](#9090)
- fix cli token command for token resolution by @roele in
[#9077](#9077)

### 📦 Registry

- add trzsz-go
([aqua:trzsz/trzsz-go](https://github.com/trzsz/trzsz-go)) by
@ZeroAurora in [#9083](#9083)
- add copilot
([aqua:github/copilot-cli](https://github.com/github/copilot-cli)) by
@risu729 in [#9082](#9082)

### Chore

- add AGENTS.md symlink by @jdx in
[#9094](#9094)

### New Contributors

- @kevinswiber made their first contribution in
[#9071](#9071)
- @webkaz made their first contribution in
[#9072](#9072)
- @RobertDeRose made their first contribution in
[#9088](#9088)

## 📦 Aqua Registry Updates

#### New Packages (7)

-
[`IBM-Cloud/ibm-cloud-cli-release`](https://github.com/IBM-Cloud/ibm-cloud-cli-release)
- [`max-sixty/worktrunk`](https://github.com/max-sixty/worktrunk)
- [`micelio.dev/hif`](https://github.com/micelio.dev/hif)
- [`pgplex/pgschema`](https://github.com/pgplex/pgschema)
-
[`rose-pine/rose-pine-bloom`](https://github.com/rose-pine/rose-pine-bloom)
- [`santosr2/TerraTidy`](https://github.com/santosr2/TerraTidy)
- [`trzsz/trzsz-go`](https://github.com/trzsz/trzsz-go)

#### Updated Packages (3)

- [`mvdan/sh`](https://github.com/mvdan/sh)
- [`rvben/rumdl`](https://github.com/rvben/rumdl)
- [`temporalio/temporal`](https://github.com/temporalio/temporal)
netbsd-srcmastr pushed a commit to NetBSD/pkgsrc that referenced this pull request Apr 16, 2026
## [2026.4.14](https://github.com/jdx/mise/compare/v2026.4.13..v2026.4.14) - 2026-04-15

### Chore

- bump sigstore-verification by @jdx in [#9128](jdx/mise#9128)

## [2026.4.13](https://github.com/jdx/mise/compare/v2026.4.12..v2026.4.13) - 2026-04-15

### 🐛 Bug Fixes

- **(go)** honor install_before for module versions by @mariusvniekerk in [#9097](jdx/mise#9097)
- **(vfox-plugin)** support Git URL with commit hash for mise.toml by @Oyami-Srk in [#9099](jdx/mise#9099)
- `MISE_FETCH_REMOTE_VERSIONS_CACHE` not respected by @mcncl in [#9096](jdx/mise#9096)

### 📦️ Dependency Updates

- unblock cargo-deny advisories check by @jdx in [#9112](jdx/mise#9112)

### New Contributors

- @mariusvniekerk made their first contribution in [#9097](jdx/mise#9097)
- @mcncl made their first contribution in [#9096](jdx/mise#9096)
- @Oyami-Srk made their first contribution in [#9099](jdx/mise#9099)

## [2026.4.12](https://github.com/jdx/mise/compare/v2026.4.11..v2026.4.12) - 2026-04-15

### 🚀 Features

- **(npm)** use --min-release-age for npm 11.10.0+ supply chain protection by @webkaz in [#9072](jdx/mise#9072)
- **(registry)** add openfga by @mnm364 in [#9084](jdx/mise#9084)
- **(task)** allow to set confirmation default by @roele in [#9089](jdx/mise#9089)
- support os/arch compound syntax in tool os filtering by @RobertDeRose in [#9088](jdx/mise#9088)

### 🐛 Bug Fixes

- **(activate)** export __MISE_EXE and resolve bare ARGV0 to absolute path by @fru1tworld in [#9081](jdx/mise#9081)
- **(install)** support aliased installs sharing a backend by @jdx in [#9093](jdx/mise#9093)
- **(shim)** use which_no_shims when resolving mise binary in reshim and doctor by @kevinswiber in [#9071](jdx/mise#9071)
- filter empty segments in colon-separated env var parsing by @baby-joel in [#9076](jdx/mise#9076)

### 📚 Documentation

- fix wrong file reference to forgejo backend implemenation by @roele in [#9090](jdx/mise#9090)
- fix cli token command for token resolution by @roele in [#9077](jdx/mise#9077)
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