Skip to content

fix(hook-env): skip remote version fetching for uninstalled tools in prefer-offline mode#7976

Merged
jdx merged 10 commits intomainfrom
fix/hook-env-skip-remote-fetch
Feb 3, 2026
Merged

fix(hook-env): skip remote version fetching for uninstalled tools in prefer-offline mode#7976
jdx merged 10 commits intomainfrom
fix/hook-env-skip-remote-fetch

Conversation

@jdx
Copy link
Owner

@jdx jdx commented Feb 3, 2026

Summary

  • When a tool version (e.g. poetry 2.3.2) is in .tool-versions but not installed locally, resolve_version() makes an HTTP request to validate the version exists remotely
  • In prefer-offline mode (hook-env, activate, exec, etc.), this adds ~370ms of latency to every shell prompt
  • Skip remote version fetching for uninstalled tools when PREFER_OFFLINE is true — accept the version string as-is since it will be validated when mise install is run

Fixes #7974

Test plan

  • mise run build — compiles successfully
  • mise run test:unit — all 445 tests pass
  • mise run lint — all lints pass
  • Manual test: create .tool-versions with poetry 2.3.2, run MISE_TRACE=1 mise hook-env and verify no HTTP request to mise-versions.jdx.dev

🤖 Generated with Claude Code


Note

Medium Risk
Changes version resolution behavior in PREFER_OFFLINE mode, which could cause uninstalled pinned versions to be accepted without remote validation until install-time. Low implementation complexity but touches core resolution logic used broadly (hook-env/activate/exec).

Overview
Reduces prompt latency in prefer-offline workflows by updating ToolVersion::resolve_version to skip remote version fetching when PREFER_OFFLINE is set and the requested version looks fully pinned (e.g. x.y.z) but isn’t installed; prefix requests (e.g. x) still resolve remotely.

Also memoizes aqua package suggestions via a process-wide AQUA_SUGGESTIONS_CACHE to avoid rebuilding the name-to-ID index on each aqua_suggest call, and tweaks the mise install warning text to say tools are "not in any config file" (vs only mise.toml).

Written by Cursor Bugbot for commit 33626be. This will update automatically on new commits. Configure here.

jdx and others added 8 commits February 2, 2026 12:44
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
When a user types an unknown tool name (e.g. `mise use foo`), instead of
just failing with "not found in registry", suggest similar tools from both
the mise registry and aqua registry using Jaro-Winkler string similarity.

- Bump xx to 2.5 for the suggest module
- Add package_ids() to aqua-registry crate for querying available tools
- Add aqua_suggest() for fuzzy-matching aqua package names
- Replace plain error in backend_arg with "Did you mean?" suggestions

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
When running `mise install <tool>` for a tool not in any mise.toml or
.tool-versions file, show a warning suggesting `mise use` instead.
Also adds e2e tests for both the "Did you mean?" and inactive tool features.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Use HashMap for O(1) lookup in aqua_suggest instead of nested loops
- Deduplicate suggestions: skip aqua tools whose name matches a mise suggestion
- Skip inactive tool warning in dry-run mode

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
…prefer-offline mode

When a tool version is specified but not installed locally, resolve_version()
would make an HTTP request to validate the version exists remotely. In
prefer-offline mode (hook-env, activate, exec, etc.), this adds ~370ms of
latency to every shell prompt. Skip the remote fetch and accept the version
string as-is — it will be validated when the user runs `mise install`.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings February 3, 2026 02:50
@gemini-code-assist
Copy link
Contributor

Summary of Changes

Hello @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 primarily focuses on optimizing mise's performance in prefer-offline mode by eliminating unnecessary remote version checks, thereby reducing shell prompt latency. It also significantly enhances the command-line interface by introducing intelligent "Did you mean?" suggestions for mistyped tool names and providing helpful guidance when users install tools that are not yet activated in their configuration.

Highlights

  • Performance Improvement for prefer-offline mode: Remote version fetching for uninstalled tools is now skipped when PREFER_OFFLINE is enabled, significantly reducing latency in shell prompts, especially for commands like hook-env.
  • Enhanced Tool Suggestion System: Implemented "Did you mean?" suggestions for unknown tools in the mise tool registry, including relevant Aqua packages, improving user experience for typos and discovery.
  • Informative mise install Warnings: Users are now warned when mise install is used for tools not activated in any config file, with clear suggestions on how to activate them using mise use.
  • Dependency Updates: Numerous Rust dependencies in Cargo.lock have been updated, including itertools, windows-sys, lzma-rust2, socket2, base64, reqwest, zip, and typed-path, along with additions like serde and js-sys.
Changelog
  • Cargo.lock
    • Updated itertools from 0.13.0 to 0.10.5 (and 0.14.0 to 0.10.5).
    • Updated windows-sys across multiple packages from 0.61.2 to 0.59.0 (and 0.60.2 to 0.59.0, 0.45.0).
    • Updated crc from 3.4.0 to 3.3.0.
    • Updated lzma-rust2 from 0.13.0 to 0.15.7 (and removed a duplicate entry).
    • Updated socket2 from 0.6.2 to 0.5.10.
    • Updated windows-core from 0.62.2 to a versionless dependency in several places, and removed a specific windows-core package entry.
    • Updated base64 from 0.22.1 to 0.21.7.
    • Updated errno from 0.3.14 to 0.2.8.
    • Updated reqwest from 0.12.28 to 0.13.1.
    • Updated zip from 6.0.0 to 7.2.0.
    • Updated typed-path from a versionless dependency to 0.9.3 and added a new typed-path entry for 0.12.2.
    • Added serde, serde_json, serde_urlencoded, strsim, generic-array, js-sys as new dependencies in various packages.
    • Updated xx from 2.3.0 to 2.5.1.
  • crates/aqua-registry/src/lib.rs
    • Exported the new package_ids function from the registry module.
  • crates/aqua-registry/src/registry.rs
    • Added a new public function package_ids to retrieve all package IDs from the AQUA_STANDARD_REGISTRY_FILES.
  • e2e/cli/test_did_you_mean
    • Added a new end-to-end test script to verify "Did you mean?" suggestions for unknown tools, including typos for mise registry tools and Aqua packages.
  • e2e/cli/test_install_inactive_hint
    • Added a new end-to-end test script to verify that mise install warns when installing tools not activated in any config file and suggests mise use.
  • src/aqua/aqua_registry_wrapper.rs
    • Introduced a new public function aqua_suggest that searches Aqua packages by tool name and returns similar "owner/name" IDs based on a similarity threshold.
  • src/cli/args/backend_arg.rs
    • Modified the error handling for unknown tools to incorporate "Did you mean?" suggestions. It now uses xx::suggest for mise registry tools and aqua_suggest for Aqua packages, presenting up to 5 suggestions.
  • src/cli/install.rs
    • Added logic to identify tools installed via mise install that are not present in any active configuration file.
    • Implemented a warning message that is displayed after installation for such inactive tools, providing mise use commands to activate them.
  • src/toolset/tool_version.rs
    • Imported the env module.
    • Added a conditional check in resolve_version to skip remote version fetching if the PREFER_OFFLINE environment variable is set to true, directly returning the provided version string.
Activity
  • The project successfully compiled after running mise run build.
  • All 445 unit tests passed when executing mise run test:unit.
  • All lints passed after running mise run lint.
  • A manual test confirmed that MISE_TRACE=1 mise hook-env does not make HTTP requests to mise-versions.jdx.dev when PREFER_OFFLINE is active, as intended.
Using Gemini Code Assist

The 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 /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

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 .gemini/ folder in the base of the repository. Detailed instructions can be found here.

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

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR optimizes shell prompt performance by skipping remote version fetching for uninstalled tools when running in prefer-offline mode (e.g., hook-env, activate). Additionally, it improves the user experience with better error messages and warnings.

Changes:

  • Skip HTTP requests to validate remote versions for uninstalled tools in prefer-offline mode
  • Add "Did you mean?" suggestions when tools are not found in the registry
  • Warn users when installing tools that aren't activated in any config file

Reviewed changes

Copilot reviewed 8 out of 9 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
src/toolset/tool_version.rs Early return in resolve_version() when PREFER_OFFLINE is true to skip remote version fetching
src/cli/install.rs Track and warn about installed tools not present in config files
src/cli/args/backend_arg.rs Add "Did you mean?" suggestions for unknown tools using both mise and aqua registries
src/aqua/aqua_registry_wrapper.rs Implement aqua_suggest() function to find similar tool names in aqua registry
crates/aqua-registry/src/registry.rs Add package_ids() helper to expose all aqua package IDs
crates/aqua-registry/src/lib.rs Export package_ids function
e2e/cli/test_install_inactive_hint Add test for inactive tool installation warning
e2e/cli/test_did_you_mean Add test for "Did you mean?" suggestions

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

// Build a map from tool name to full IDs for O(1) lookup
let mut name_to_ids: HashMap<&str, Vec<&str>> = HashMap::new();
for id in &ids {
if let Some((_, name)) = id.rsplit_once('/') {
Copy link

Copilot AI Feb 3, 2026

Choose a reason for hiding this comment

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

The underscore binding _ discards the owner portion of the ID. Consider using a more descriptive name like _owner to clarify what's being ignored, improving code readability.

Suggested change
if let Some((_, name)) = id.rsplit_once('/') {
if let Some((_owner, name)) = id.rsplit_once('/') {

Copilot uses AI. Check for mistakes.
// Map back to full IDs
let mut results = Vec::new();
for matched_name in &similar_names {
if let Some(full_ids) = name_to_ids.get(matched_name.as_str()) {
Copy link

Copilot AI Feb 3, 2026

Choose a reason for hiding this comment

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

The .as_str() call is unnecessary here since matched_name is already &str from the iteration. This adds a redundant string conversion.

Suggested change
if let Some(full_ids) = name_to_ids.get(matched_name.as_str()) {
if let Some(full_ids) = name_to_ids.get(matched_name) {

Copilot uses AI. Check for mistakes.
Copy link
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 introduces several valuable user experience enhancements, including 'did you mean' suggestions for tool names and warnings for installing inactive tools. The primary fix to skip remote version fetching in prefer-offline mode is also correctly implemented. The code is generally well-structured and includes new tests for the added features. I've identified one critical issue that could lead to a compile error due to a moved value, which should be addressed. Additionally, I've provided a suggestion to improve the performance of the new suggestion feature by caching some data, and a minor wording improvement for a new warning message to enhance clarity.

I am having trouble creating individual review comments. Click here to see my feedback.

src/toolset/tool_version.rs (251-253)

critical

The v variable, which is a String, is moved in other branches of this function (e.g., at line 245 if an installed version is found). This new branch also moves v by calling build(v). If a previous branch that moves v is not taken, this code will compile, but it creates a situation where v is used after being moved if other branches are considered.

This will likely lead to a compile error about using a moved value. To fix this and ensure v can be used in subsequent parts of the function, you should clone it.

I'd also recommend checking other calls to build(v) in this function to ensure they also use v.clone() if v is needed later.

        if env::PREFER_OFFLINE.load(std::sync::atomic::Ordering::Relaxed) {
            return build(v.clone());
        }

src/aqua/aqua_registry_wrapper.rs (121-150)

medium

The name_to_ids map and names vector are rebuilt on every call to aqua_suggest. Since the underlying data from aqua_registry::package_ids() is static, this computation can be cached using LazyLock to improve performance, especially if this function is called multiple times (e.g., with multiple typos).

I suggest creating a static cached structure to hold both the map and the list of names.

use std::sync::LazyLock;

struct AquaSuggestionsCache {
    name_to_ids: HashMap<&'static str, Vec<&'static str>>,
    names: Vec<&'static str>,
}

static AQUA_SUGGESTIONS_CACHE: LazyLock<AquaSuggestionsCache> = LazyLock::new(|| {
    let ids = aqua_registry::package_ids();
    let mut name_to_ids: HashMap<&'static str, Vec<&'static str>> = HashMap::new();
    for id in &ids {
        if let Some((_, name)) = id.rsplit_once('/') {
            name_to_ids.entry(name).or_default().push(id);
        }
    }
    let names = name_to_ids.keys().copied().collect();
    AquaSuggestionsCache { name_to_ids, names }
});

/// Search aqua packages by tool name, returning "owner/name" IDs
/// where the name part is similar to the query.
pub fn aqua_suggest(query: &str) -> Vec<String> {
    // Use a higher threshold (0.8) to avoid noisy suggestions
    let similar_names = xx::suggest::similar_n_with_threshold(
        query,
        &AQUA_SUGGESTIONS_CACHE.names,
        5,
        0.8,
    );

    // Map back to full IDs
    let mut results = Vec::new();
    for matched_name in &similar_names {
        if let Some(full_ids) = AQUA_SUGGESTIONS_CACHE.name_to_ids.get(matched_name.as_str()) {
            for full_id in full_ids {
                results.push(full_id.to_string());
                if results.len() >= 5 {
                    return results;
                }
            }
        }
    }
    results
}

src/cli/install.rs (168)

medium

The warning message specifically mentions mise.toml, but mise can use other configuration files like .tool-versions. A more generic message like "not in any config file" would be more accurate and less confusing for users who might be using other configuration files.

                "{tool_list} installed but not activated — {} not in any config file.\nTo install and activate, run:\n{}",

- Only skip remote version fetch for fully-qualified versions (2+ dots)
  to avoid breaking prefix resolution (e.g. "2" → "2.1.0")
- Cache aqua suggestions data with LazyLock instead of rebuilding on
  every call
- Use generic "config file" wording instead of "mise.toml" in install
  warning since .tool-versions is also valid

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
@github-actions
Copy link

github-actions bot commented Feb 3, 2026

Hyperfine Performance

mise x -- echo

Command Mean [ms] Min [ms] Max [ms] Relative
mise-2026.2.1 x -- echo 20.1 ± 0.3 19.6 23.1 1.00
mise x -- echo 20.3 ± 0.2 19.8 21.6 1.01 ± 0.02

mise env

Command Mean [ms] Min [ms] Max [ms] Relative
mise-2026.2.1 env 19.6 ± 0.5 19.0 23.8 1.00
mise env 19.7 ± 0.2 19.2 21.0 1.01 ± 0.03

mise hook-env

Command Mean [ms] Min [ms] Max [ms] Relative
mise-2026.2.1 hook-env 20.4 ± 0.4 19.7 24.8 1.00
mise hook-env 20.5 ± 0.2 20.0 21.5 1.01 ± 0.02

mise ls

Command Mean [ms] Min [ms] Max [ms] Relative
mise-2026.2.1 ls 18.5 ± 0.3 17.9 19.7 1.00
mise ls 18.5 ± 0.2 18.0 19.6 1.00 ± 0.02

xtasks/test/perf

Command mise-2026.2.1 mise Variance
install (cached) 113ms 110ms +2%
ls (cached) 70ms 70ms +0%
bin-paths (cached) 74ms 74ms +0%
task-ls (cached) 544ms 542ms +0%

@jdx jdx merged commit 6d491c4 into main Feb 3, 2026
36 checks passed
@jdx jdx deleted the fix/hook-env-skip-remote-fetch branch February 3, 2026 09:44
mise-en-dev added a commit that referenced this pull request Feb 3, 2026
### 🚀 Features

- **(asset-matcher)** enable `mingw-w64` detection for windows packages
by @lchagnoleau in [#7981](#7981)
- **(crates/vfox)** add download_path to BackendInstall context by
@malept in [#7959](#7959)
- **(python)** rework `python.uv_venv_auto` setting by @halms in
[#7905](#7905)
- add "Did you mean?" suggestions and inactive tool warnings by @jdx in
[#7965](#7965)

### 🐛 Bug Fixes

- **(hook-env)** skip remote version fetching for uninstalled tools in
prefer-offline mode by @jdx in
[#7976](#7976)
- **(install.sh)** Corret `setup` to `set up` by @gogolok in
[#7980](#7980)
- retry spawn on ETXTBSY (Text file busy) by @jdx in
[#7964](#7964)
- improve ToolOptions parsing to support comma separated values by
@roele in [#7971](#7971)

### 📚 Documentation

- improve plugin documentation with comparisons and template links by
@jdx in [#7962](#7962)

### 📦️ Dependency Updates

- bump hyper-util, system-configuration, lru, aws-sdk, and others by
@jdx in [#7977](#7977)

### Chore

- **(vfox)** add LuaCATS type definitions for plugin IDE support by @jdx
in [#7961](#7961)
- **(vfox)** add `download_path` to `BackendInstallCtx` type defintion
by @malept in [#7973](#7973)
- add stylua linting for vfox plugin Lua files by @jdx in
[#7960](#7960)
- use system Rust for PPA builds on Ubuntu 26.04+ by @jdx in
[#7956](#7956)

### New Contributors

- @gogolok made their first contribution in
[#7980](#7980)

## 📦 Aqua Registry Updates

#### New Packages (4)

- [`autobrr/mkbrr`](https://github.com/autobrr/mkbrr)
- [`dodobrands/Peekie`](https://github.com/dodobrands/Peekie)
-
[`grpc/grpc-java/protoc-gen-grpc-java`](https://github.com/grpc/grpc-java/protoc-gen-grpc-java)
-
[`str4d/age-plugin-yubikey`](https://github.com/str4d/age-plugin-yubikey)

#### Updated Packages (3)

- [`biomejs/biome`](https://github.com/biomejs/biome)
-
[`rust-cross/cargo-zigbuild`](https://github.com/rust-cross/cargo-zigbuild)
- [`siderolabs/talos`](https://github.com/siderolabs/talos)
lucasew pushed a commit to lucasew/CONTRIB-mise that referenced this pull request Feb 18, 2026
…prefer-offline mode (jdx#7976)

## Summary
- When a tool version (e.g. `poetry 2.3.2`) is in `.tool-versions` but
not installed locally, `resolve_version()` makes an HTTP request to
validate the version exists remotely
- In prefer-offline mode (`hook-env`, `activate`, `exec`, etc.), this
adds ~370ms of latency to every shell prompt
- Skip remote version fetching for uninstalled tools when
`PREFER_OFFLINE` is true — accept the version string as-is since it will
be validated when `mise install` is run

Fixes jdx#7974

## Test plan
- [x] `mise run build` — compiles successfully
- [x] `mise run test:unit` — all 445 tests pass
- [x] `mise run lint` — all lints pass
- [ ] Manual test: create `.tool-versions` with `poetry 2.3.2`, run
`MISE_TRACE=1 mise hook-env` and verify no HTTP request to
mise-versions.jdx.dev

🤖 Generated with [Claude Code](https://claude.com/claude-code)

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Medium Risk**
> Changes version resolution behavior in `PREFER_OFFLINE` mode, which
could cause uninstalled pinned versions to be accepted without remote
validation until install-time. Low implementation complexity but touches
core resolution logic used broadly (hook-env/activate/exec).
> 
> **Overview**
> Reduces prompt latency in *prefer-offline* workflows by updating
`ToolVersion::resolve_version` to **skip remote version fetching** when
`PREFER_OFFLINE` is set and the requested version looks fully pinned
(e.g. `x.y.z`) but isn’t installed; prefix requests (e.g. `x`) still
resolve remotely.
> 
> Also **memoizes aqua package suggestions** via a process-wide
`AQUA_SUGGESTIONS_CACHE` to avoid rebuilding the name-to-ID index on
each `aqua_suggest` call, and tweaks the `mise install` warning text to
say tools are "not in any config file" (vs only `mise.toml`).
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
33626be. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->

---------

Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
lucasew pushed a commit to lucasew/CONTRIB-mise that referenced this pull request Feb 18, 2026
### 🚀 Features

- **(asset-matcher)** enable `mingw-w64` detection for windows packages
by @lchagnoleau in [jdx#7981](jdx#7981)
- **(crates/vfox)** add download_path to BackendInstall context by
@malept in [jdx#7959](jdx#7959)
- **(python)** rework `python.uv_venv_auto` setting by @halms in
[jdx#7905](jdx#7905)
- add "Did you mean?" suggestions and inactive tool warnings by @jdx in
[jdx#7965](jdx#7965)

### 🐛 Bug Fixes

- **(hook-env)** skip remote version fetching for uninstalled tools in
prefer-offline mode by @jdx in
[jdx#7976](jdx#7976)
- **(install.sh)** Corret `setup` to `set up` by @gogolok in
[jdx#7980](jdx#7980)
- retry spawn on ETXTBSY (Text file busy) by @jdx in
[jdx#7964](jdx#7964)
- improve ToolOptions parsing to support comma separated values by
@roele in [jdx#7971](jdx#7971)

### 📚 Documentation

- improve plugin documentation with comparisons and template links by
@jdx in [jdx#7962](jdx#7962)

### 📦️ Dependency Updates

- bump hyper-util, system-configuration, lru, aws-sdk, and others by
@jdx in [jdx#7977](jdx#7977)

### Chore

- **(vfox)** add LuaCATS type definitions for plugin IDE support by @jdx
in [jdx#7961](jdx#7961)
- **(vfox)** add `download_path` to `BackendInstallCtx` type defintion
by @malept in [jdx#7973](jdx#7973)
- add stylua linting for vfox plugin Lua files by @jdx in
[jdx#7960](jdx#7960)
- use system Rust for PPA builds on Ubuntu 26.04+ by @jdx in
[jdx#7956](jdx#7956)

### New Contributors

- @gogolok made their first contribution in
[jdx#7980](jdx#7980)

## 📦 Aqua Registry Updates

#### New Packages (4)

- [`autobrr/mkbrr`](https://github.com/autobrr/mkbrr)
- [`dodobrands/Peekie`](https://github.com/dodobrands/Peekie)
-
[`grpc/grpc-java/protoc-gen-grpc-java`](https://github.com/grpc/grpc-java/protoc-gen-grpc-java)
-
[`str4d/age-plugin-yubikey`](https://github.com/str4d/age-plugin-yubikey)

#### Updated Packages (3)

- [`biomejs/biome`](https://github.com/biomejs/biome)
-
[`rust-cross/cargo-zigbuild`](https://github.com/rust-cross/cargo-zigbuild)
- [`siderolabs/talos`](https://github.com/siderolabs/talos)
jdx added a commit that referenced this pull request Mar 7, 2026
… mode

In prefer-offline mode (used by `mise env`, `hook-env`, `activate`, `exec`),
"latest" versions were not covered by the prefer_offline guard, causing
unnecessary network calls to package registries. This is especially
problematic with private npm registries where the call can hang indefinitely.

The existing prefer_offline guard (added in #7976) only covered
fully-qualified versions (e.g. "2.3.2"). This adds the same guard for
"latest" versions: if a version is already installed, it's returned;
otherwise "latest" is returned as-is without a network fetch.

Fixes #8499

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
jdx added a commit that referenced this pull request Mar 7, 2026
… mode (#8500)

## Summary

- Adds `prefer_offline` guard for `"latest"` versions in
`resolve_version()`, matching the existing guard for fully-qualified
versions added in #7976
- Prevents `mise env`, `hook-env`, `activate`, and `exec` from making
network calls when resolving `"latest"` versions — avoiding hangs with
private npm registries

## Context

After lockfiles graduated from experimental in v2026.2.0 (#7929), `mise
env --json` with `npm:pkg = "latest"` and no lockfile entry falls
through to a network fetch that `prefer_offline` mode was intended to
prevent. If the private registry holds the TCP connection open (waiting
for credentials), mise hangs indefinitely.

PR #7976 fixed this for fully-qualified versions (e.g. `"2.3.2"`) but
the `"latest"` path was not covered. This one-liner closes that gap.

See #8499 for the full root cause analysis.

Fixes #8499

## Test plan

- [ ] `mise env --json` with `npm:pkg = "latest"` and no registry auth
no longer makes network calls or hangs
- [ ] Existing behavior unchanged when `prefer_offline` is not set (e.g.
`mise install` still resolves latest from registry)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Low Risk**
> Small conditional change to version resolution logic that only affects
`prefer_offline` behavior for `latest`; low risk but could change
expectations for users relying on remote latest lookup in that mode.
> 
> **Overview**
> Prevents network access when resolving `"latest"` in
`ToolVersion::resolve_version` while `prefer_offline` is enabled,
aligning `latest` behavior with the existing prefer-offline skip for
fully-qualified versions.
> 
> This adds a guard so `hook-env`/`activate`/`exec`/`env` won’t call
`latest_version_with_opts` unless explicitly doing a latest-version
lookup (`opts.latest_versions`), avoiding hangs against registries that
keep connections open.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
1ecf269. 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>
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