jdx/mise · error

package plugin '{}' does not support uninstall; add hooks/pa

Error message

package plugin '{}' does not support uninstall; add hooks/package_uninstall.lua

What it means

A package plugin can only uninstall packages if it provides a hooks/package_uninstall.lua hook. During apply_prune_plan, after computing packages that should be removed, mise refuses to proceed when the plugin lacks uninstall support rather than silently leaving installed packages behind.

Source

Thrown at src/system/packages/plugin.rs:444

        let before = self.installed(&requests).await?;
        let present = before
            .iter()
            .filter_map(|status| {
                Self::status_version(status).map(|version| PackageRequest {
                    name: status.request.name.clone(),
                    version: Some(version),
                    tap_url: None,
                    desired: crate::system::packages::PackageDesiredState::Present,
                })
            })
            .collect::<Vec<_>>();
        Self::reconcile_missing_ownership(&mut state, &before);
        self.save_state(&state)?;
        if present.is_empty() {
            return Ok(0);
        }
        if !self.supports_uninstall() {
            bail!(
                "package plugin '{}' does not support uninstall; add hooks/package_uninstall.lua",
                self.name
            );
        }

        let action_result = self.uninstall_action(&present).await;
        let after = self.installed(&present).await;
        let after = match after {
            Ok(after) => after,
            Err(status_err) => {
                if let Err(action_err) = action_result {
                    warn!(
                        "{}: failed to verify uninstall after error: {status_err:#}",
                        self.name
                    );
                    return Err(action_err);
                }
                return Err(status_err);

View on GitHub (pinned to afd2eddd3a)

Solutions

  1. Add a hooks/package_uninstall.lua to the plugin implementing package removal
  2. Uninstall the package manually with the underlying manager and clear ownership state, then prune once uninstall support exists
  3. Keep the package installed (don't remove it from config) if the plugin cannot uninstall
  4. Update the plugin to a version that ships package_uninstall.lua

Example fix

// before: plugin dir lacks the hook
mise plugins packages prune myplugin
// error: package plugin 'myplugin' does not support uninstall
// after: add hooks/package_uninstall.lua
-- function mise_package_uninstall(ctx) ... end
mise plugins packages prune myplugin
Defensive patterns

Strategy: validation

Validate before calling

let hook = plugin.dir().join("hooks/package_uninstall.lua");
if !hook.exists() { /* skip prune or uninstall manually */ }

Type guard

fn supports_uninstall(dir: &Path) -> bool { dir.join("hooks/package_uninstall.lua").is_file() }

Try / catch

match plugin.prune().await {
    Err(e) if e.to_string().contains("does not support uninstall") => {
        warn("plugin cannot uninstall; removing packages manually"); manual_uninstall_tracked()
    }
    other => other,
}

Prevention

When it happens

Trigger: A prune/uninstall operation (apply_prune_plan) targets packages that must be removed, but the plugin directory has no hooks/package_uninstall.lua so supports_uninstall() returns false.

Common situations: Using a plugin written only for installation (install/check hooks) and later trying `mise packages prune` or removing the package from config; older plugin versions predating the uninstall hook convention.

Related errors


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