jdx/mise · error

bail!(msg) — dynamic message: uninstalled tool message from

Error message

bail!(msg) — dynamic message: uninstalled tool message from which.rs uninstalled_tool_message()

What it means

mise's `mise which <bin>` failed because the binary resolves to a configured tool version that is not installed on disk. Rather than saying 'not a tool', mise detects that the toolset pins the tool and emits a targeted message (from uninstalled_tool_message()) telling the user the tool exists in config but has never been installed. This is a user-environment error, not an internal bug.

Source

Thrown at src/cli/which.rs:75

        }
        let ts = self.get_toolset(&config).await?;

        let bin_name = self.bin_name.clone().unwrap();
        match ts.which(&config, &bin_name).await {
            Some((p, tv)) => {
                if self.version {
                    miseprintln!("{}", tv.version);
                } else if self.plugin {
                    miseprintln!("{p}");
                } else {
                    let path = p.which(&config, &tv, &bin_name).await?;
                    miseprintln!("{}", path.unwrap().display());
                }
                Ok(())
            }
            None => {
                if let Some(msg) = self.uninstalled_tool_message(&config, &ts) {
                    bail!(msg);
                }
                if let Some(msg) =
                    crate::shims::unavailable_configured_tool_message(&config, &ts, &bin_name)
                {
                    bail!(msg);
                }
                if self.has_shim(&bin_name) {
                    bail!(
                        "{bin_name} is a mise bin however it is not currently active. Use `mise use` to activate it in this directory."
                    )
                } else {
                    bail!("{bin_name} is not a mise bin. Perhaps you need to install it first.",)
                }
            }
        }
    }
    async fn complete(&self, config: &Arc<Config>) -> Result<()> {
        let ts = self.get_toolset(config).await?;

View on GitHub (pinned to afd2eddd3a)

Solutions

  1. Run `mise install` to install all tools pinned in the active config files.
  2. Run `mise install <tool>@<version>` to install just the tool mentioned in the message.
  3. Run `mise ls` to compare installed vs configured versions and spot gaps.
  4. If the version in config is no longer wanted, update mise.toml/.tool-versions to an installed version.

Example fix

// shell: before (fresh clone)
mise which node
# error: node@22.1.0 is not installed
// after
mise install
mise which node
# /home/user/.local/share/mise/installs/node/22.1.0/bin/node
Defensive patterns

Strategy: validation

Validate before calling

# before relying on `mise which <bin>`
mise ls --installed | grep '<tool>' || mise install

Try / catch

if ! out=$(mise which "$bin" 2>/dev/null); then mise install; fi

Prevention

When it happens

Trigger: Running `mise which <bin>` (or a shim calling which) when config (mise.toml/.tool-versions) pins a tool version whose install directory does not exist, e.g. after cloning a repo with a mise.toml on a fresh machine, after deleting ~/.local/share/mise/installs, or with MISE_XX_VERSION pinned to an uninstalled version.

Common situations: Fresh checkout of a project without running `mise install`; CI containers with config files but no installed tools; moving/cleaning the mise data directory; disk cleanup removing installs while config still references them.

Understand the failure class

Background: 'Could not be found', 'does not exist', 'not found in database': the resource-not-found family when an ID, slug, key, or URI lookup comes back empty — this error's family across 20 libraries.

Related errors


AI-assisted analysis of jdx/mise@afd2eddd3a (2026-09-09). Data as JSON: /api/errors/52dfbaa57dd6b323. Report an issue: GitHub.