jdx/mise · error

is not installed

Error message

{ba} is not installed

What it means

`mise ls` verifies that each tool/plugin selected for display is actually installed. When a requested backend maps to an asdf/vfox-style plugin whose `is_installed()` check fails, it bails with "<tool> is not installed". It is a precondition check before listing versions.

Solutions

  1. Install the missing plugin/tool: `mise install <tool>` or `mise plugin install <tool>`
  2. Check installed plugins with `mise plugins ls` and add the missing one
  3. Fix the tool name in your mise.toml/.tool-versions if it is a typo
  4. Remove the stale tool entry if the tool is no longer needed

Example fix

// mise.toml before
[tools]
node = "20"
unknownplugin = "1.0"
// after (install it or remove the entry)
mise install unknownplugin
Defensive patterns

Strategy: validation

Validate before calling

mise plugins ls | grep -q "^node$" || mise plugin install node

Prevention

When it happens

Trigger: Running `mise ls <tool>` (or with `--installed-tool` selections) where the tool's backend has a plugin that is not installed on the machine.

Common situations: Referencing a tool in .tool-versions/mise.toml whose plugin was never installed (e.g. after cloning a project config), a plugin that was removed or corrupted in ~/.local/share/mise/plugins, or typos in tool names.

Understand the failure class

Background: "not installed", "pip install", "required for": how missing-dependency errors surface across open-source libraries — this error's family across 34 libraries.

Related errors


AI-assisted analysis of jdx/mise@533346cc37 (2026-09-17). Data as JSON: /api/errors/f401ded81461a963. Report an issue: GitHub.

Appendix: source

Thrown at src/cli/ls.rs:192

            Err(err) => {
                warn!("failed to read tool purgatory state: {err:#}");
                BTreeMap::new()
            }
        };
        if self.json {
            self.display_json(&config, runtimes, sources_map.as_ref(), &scheduled_removals)
                .await
        } else {
            self.display_user(&config, runtimes, sources_map.as_ref(), &scheduled_removals)
                .await
        }
    }

    fn verify_plugin(&self) -> Result<()> {
        if let Some(plugins) = &self.installed_tool {
            for ba in plugins {
                if let Some(plugin) = ba.backend()?.plugin() {
                    ensure!(plugin.is_installed(), "{ba} is not installed");
                }
            }
        }
        Ok(())
    }

    async fn display_json(
        &self,
        config: &Arc<Config>,
        runtimes: Vec<RuntimeRow<'_>>,
        sources_map: Option<&SourcesMap>,
        scheduled_removals: &BTreeMap<PathBuf, u64>,
    ) -> Result<()> {
        if let Some(plugins) = &self.installed_tool {
            // only runtimes for 1 plugin
            let runtimes: Vec<RuntimeRow<'_>> = runtimes
                .into_iter()
                .filter(|(_, p, _, _)| matches_requested_tool(plugins, p.ba()))

View on GitHub (pinned to 533346cc37)