fix(install): skip remote-versions refresh in prefer-offline mode#9627
fix(install): skip remote-versions refresh in prefer-offline mode#9627
Conversation
In prefer_offline mode (shims, hook-env, activate, etc.) the versions host is disabled. Refreshing the cache there bypasses the on-disk list populated by an earlier non-prefer-offline command and falls through to a backend listing that often has far fewer versions (e.g. GitHub releases only returns the ~30 most recent), turning a previously- resolvable prefix query into "no versions found for <tool>". Reported on commit aafe53f — terraform = "prefix:1.12" auto-install via shim broke after pre-warming with `mise install terraform`. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Greptile SummaryAdds a
Confidence Score: 5/5Safe to merge — the change is a one-line guard swap with a confirmed subsumption relationship between the old and new predicate, backed by a new regression test. The fix is minimal: a single predicate replacement in one function. prefer_offline() calls offline() internally, so every previously-guarded code path is still guarded. The new e2e test directly exercises the regression scenario. No other callers or paths are affected. No files require special attention. Reviews (2): Last reviewed commit: "test(install): cover prefer-offline cach..." | Re-trigger Greptile |
There was a problem hiding this comment.
Code Review
This pull request updates the should_refresh_remote_versions function in src/toolset/toolset_install.rs to check for prefer_offline() instead of offline(). This change, accompanied by new documentation, ensures that the on-disk cache is utilized when the versions host is disabled, preventing issues where limited backend listings fail to resolve version prefixes. I have no feedback to provide as there were no review comments.
Hyperfine Performance
|
| Command | Mean [ms] | Min [ms] | Max [ms] | Relative |
|---|---|---|---|---|
mise-2026.5.0 x -- echo |
30.9 ± 11.9 | 20.8 | 77.3 | 1.00 |
mise x -- echo |
34.8 ± 14.0 | 20.6 | 86.0 | 1.12 ± 0.62 |
x -- echo is 12% |
mise env
| Command | Mean [ms] | Min [ms] | Max [ms] | Relative |
|---|---|---|---|---|
mise-2026.5.0 env |
39.8 ± 15.7 | 20.9 | 87.2 | 1.00 |
mise env |
47.2 ± 15.2 | 20.5 | 95.9 | 1.19 ± 0.60 |
env is 19% |
mise hook-env
| Command | Mean [ms] | Min [ms] | Max [ms] | Relative |
|---|---|---|---|---|
mise-2026.5.0 hook-env |
49.7 ± 16.0 | 21.4 | 84.6 | 1.19 ± 0.63 |
mise hook-env |
41.8 ± 17.7 | 20.4 | 93.8 | 1.00 |
✅ Performance improvement for hook-env is 19% |
mise ls
| Command | Mean [ms] | Min [ms] | Max [ms] | Relative |
|---|---|---|---|---|
mise-2026.5.0 ls |
42.8 ± 17.0 | 19.9 | 85.4 | 1.00 |
mise ls |
44.0 ± 12.7 | 17.8 | 76.7 | 1.03 ± 0.51 |
xtasks/test/perf
| Command | mise-2026.5.0 | mise | Variance |
|---|---|---|---|
| install (cached) | 180ms | -12% | |
| ls (cached) | 109ms | ✅ 95ms | +14% |
| bin-paths (cached) | 131ms | ✅ 104ms | +25% |
| task-ls (cached) | 626ms | 620ms | +0% |
✅ Performance improvement: ls cached is 14%
✅ Performance improvement: bin-paths cached is 25%
Pre-warms the dummy plugin's remote_versions cache, then makes list-all fail and runs `mise install` for a `prefix:` request with no installed match under MISE_PREFER_OFFLINE=1. The buggy code path re-runs list-all via refresh_async and aborts; the fix reuses the on-disk cache. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
### 🚀 Features - **(aqua)** support registry libc variants by @jdx in [#9652](#9652) - **(bin-paths)** add executable names output by @risu729 in [#9617](#9617) ### 🐛 Bug Fixes - **(aqua)** preserve configured file extensions by @risu729 in [#9611](#9611) - **(aqua)** support registry file links by @risu729 in [#9610](#9610) - **(backend)** reject bare package backend names by @risu729 in [#9608](#9608) - **(backend)** apply inline tool option overrides by @risu729 in [#9306](#9306) - **(backend)** skip versions host for local tool opts by @risu729 in [#9568](#9568) - **(github)** chmod explicit archive bin by @risu729 in [#9609](#9609) - **(install)** skip remote-versions refresh in prefer-offline mode by @jdx in [#9627](#9627) - **(lock)** scope targets to active project root by @risu729 in [#9319](#9319) - **(lockfile)** respect existing platforms during auto-lock by @jdx in [#9621](#9621) - **(pipx)** filter yanked pypi releases by @risu729 in [#9607](#9607) - **(pipx)** declare python as a backend dependency by @jdx in [#9678](#9678) - **(schema)** update refs to $defs in mise-registry-tool.json by @risu729 in [#9671](#9671) - **(task)** terminate parallel siblings on failure via process groups by @jdx in [#9655](#9655) - **(task)** stable MISE_PROJECT_ROOT for monorepo tasks, add MISE_MONOREPO_ROOT by @jdx in [#9657](#9657) - **(trust)** run enter hooks after trusting config by @risu729 in [#9634](#9634) - **(ui)** stop clearing screen for prompts by @jdx in [#9619](#9619) - use /bin/cp on macos by @pdehlke in [#9656](#9656) ### 🚜 Refactor - **(aqua)** store aqua var defaults as strings by @risu729 in [#9645](#9645) - **(config)** support structured TOML values in registry backend options by @risu729 in [#9584](#9584) - **(deps)** remove serde_derive dependency by @risu729 in [#9670](#9670) - **(deps)** remove anyhow dependency by @risu729 in [#9661](#9661) - **(deps)** use std::sync::LazyLock instead of once_cell::Lazy by @risu729 in [#9668](#9668) - **(schema)** generate task schema from mise schema by @risu729 in [#9581](#9581) - **(schema)** reuse task props with unevaluatedProperties by @risu729 in [#9582](#9582) - **(schema)** reuse registry common types by @risu729 in [#9648](#9648) - **(schema)** reuse plugin script config by @risu729 in [#9647](#9647) - **(schema)** use $defs in schema files by @risu729 in [#9646](#9646) ### 📚 Documentation - **(node)** add tips for enabling node idiomatic by @fu050409 in [#9675](#9675) ### 🧪 Testing - **(cli)** remove nondeterministic tool depends assertion by @risu729 in [#9633](#9633) - **(e2e)** pin uv to 0.11.8 around astral-sh/uv#19278 by @jdx in [#9618](#9618) - **(e2e)** wait for docker env cleanup by @risu729 in [#9631](#9631) - **(zig)** use official zig instead of mach mirror by @jdx in [#9659](#9659) ### 📦️ Dependency Updates - fall through to hash check when providers have no outputs by @jdx in [#9622](#9622) - bump Cargo.lock by @jdx in [#9625](#9625) ### 📦 Registry - remove registry depends by @risu729 in [#9571](#9571) - add code-review-graph (pipx:code-review-graph) by @chautruonglong in [#9673](#9673) ### Chore - **(ci)** split large registry test-tool changes by @risu729 in [#9628](#9628) - **(ci)** make perf script robust to runner noise by @jdx in [#9635](#9635) - **(ci)** skip hyperfine comments without permission by @risu729 in [#9629](#9629) ### New Contributors - @chautruonglong made their first contribution in [#9673](#9673) - @pdehlke made their first contribution in [#9656](#9656) ## 📦 Aqua Registry Updates ### New Packages (5) - [`anthropics/anthropic-cli`](https://github.com/anthropics/anthropic-cli) - [`crates.io/wasmi_cli`](https://github.com/wasmi-labs/wasmi) - [`openclaw/gogcli`](https://github.com/openclaw/gogcli) - `racket-lang.org/racket-minimal` - [`runs-on/cli`](https://github.com/runs-on/cli) ### Updated Packages (13) - [`UpCloudLtd/upcloud-cli`](https://github.com/UpCloudLtd/upcloud-cli) - [`aristocratos/btop`](https://github.com/aristocratos/btop) - [`dprint/dprint`](https://github.com/dprint/dprint) - [`j178/prek`](https://github.com/j178/prek) - [`jdx/hk`](https://github.com/jdx/hk) - [`jdx/mise`](https://github.com/jdx/mise) - [`jdx/usage`](https://github.com/jdx/usage) - [`jreleaser/jreleaser`](https://github.com/jreleaser/jreleaser) - [`jreleaser/jreleaser/standalone`](https://github.com/jreleaser/jreleaser) - [`pnpm/pnpm`](https://github.com/pnpm/pnpm) - [`suzuki-shunsuke/cmdx`](https://github.com/suzuki-shunsuke/cmdx) - [`suzuki-shunsuke/ghir`](https://github.com/suzuki-shunsuke/ghir) - [`twpayne/chezmoi`](https://github.com/twpayne/chezmoi)
Summary
should_refresh_remote_versions(added in fix(install): refresh latest before installing missing tools #9545) now bails onprefer_offline()instead of justoffline().prefix:request fails after pre-warming withmise install <tool>.Why
In
prefer_offlinemode (set by shims, hook-env, activate, etc.) the versions host is disabled (versions_host.rs:71). The post-#9545 install path was forcing a cache refresh whenever no installed version matched a prefix request, which:mise install terraform).Nonebecause ofprefer_offline.terraform = \"prefix:1.10\") failed withno versions found for terraform.prefer_offline()already returns true wheneveroffline()is true, so the guard's existing offline behavior is preserved; this just additionally suppresses the cache-busting refresh on the fast paths where it would always make things worse. The original #9545 motivation (mise use <tool>getting a stale cachedlatest) is unaffected —mise usedoesn't run withPREFER_OFFLINEset.Reported on commit aafe53f: aafe53f#commitcomment-184356367
Test plan
mise install terraform(latest), then in a project withterraform = \"prefix:1.10\"invoke a terraform shim — the older prefix should resolve from cache and auto-install rather than erroring.mise use terraform@latestin a fresh shell still refreshes upstream when the cachedlatestis stale (no regression on fix(install): refresh latest before installing missing tools #9545's fix).🤖 Generated with Claude Code
Note
Medium Risk
Changes install-time version resolution behavior for prefix/latest selectors under
prefer_offline, which could affect when remote caches are refreshed and which versions get selected. Scope is small and covered by a new e2e regression test, but it touches core install resolution logic.Overview
Prevents install-time resolution from forcing a remote-versions cache refresh when running in
prefer_offlinemode, so prefix-based requests can resolve from the existing on-disk cache instead of falling back to limited backend listings.Adds an e2e regression test (
test_install_prefer_offline_no_refresh) that pre-warms the remote versions cache, pins aprefix:tool version, forcesMISE_PREFER_OFFLINE=1, and asserts the install succeeds without re-runninglist-all.Reviewed by Cursor Bugbot for commit 741cf17. Bugbot is set up for automated code reviews on this repo. Configure here.