jdx/mise · error

package plugin '{}' collides with a built-in package manager

Error message

package plugin '{}' collides with a built-in package manager

What it means

mise refuses to install a package-type plugin (PluginType::Package) whose name matches one of its built-in system package managers: apk, apt, brew, brew-cask, dnf, flatpak, flatpak-user, mas, pacman (checked via system::packages::is_builtin_manager_name). The check runs inside VfoxPlugin::install after the plugin has been cloned, so mise drops the plugin lock, deletes the freshly cloned plugin_path, and fails the install. This prevents a third-party plugin from shadowing the built-in manager used by [packages] config entries like "apt:curl = '1.0'".

Source

Thrown at src/plugins/vfox_plugin.rs:298

                        Err(PluginNotInstalled(self.name.clone()))?
                    }
                }
            }
        }

        let prefix = format!("plugin:{}", style(&self.name).blue().for_stderr());
        let pr = mpr.add_with_options(&prefix, dry_run);
        if !dry_run {
            let plugin_lock = lock_file::get(&self.plugin_path, force)?;
            self.install(config, pr.as_ref()).await?;
            let plugin_type =
                PluginType::from_plugin_path(&self.plugin_path).unwrap_or(PluginType::Vfox);
            if plugin_type == PluginType::Package
                && crate::system::packages::is_builtin_manager_name(&self.name)
            {
                drop(plugin_lock);
                file::remove_all(&self.plugin_path)?;
                bail!(
                    "package plugin '{}' collides with a built-in package manager",
                    self.name
                );
            }
            install_state::add_plugin(&self.name, plugin_type).await?;
            backend::remove(&self.name);
            warn_if_env_plugin_shadows_registry(&self.name, &self.plugin_path);
        }
        Ok(())
    }

    async fn update(&self, pr: &dyn SingleReport, gitref: Option<String>) -> Result<()> {
        // If only embedded (no filesystem plugin), warn that it can't be updated
        if self.is_embedded() && !self.plugin_path.exists() {
            warn!(
                "plugin:{} is embedded in mise, not updating",
                style(&self.name).blue().for_stderr()
            );

View on GitHub (pinned to 9dcfcaa0dc)

Solutions

  1. Rename the plugin to a non-reserved name (e.g. my-apt, company-brew) both in the repo/mise.plugin.toml and in the `mise plugin add` command, then reinstall.
  2. If you actually wanted the OS package manager, do not install a plugin at all: use the built-in manager via [packages] config keys like "apt:htop" or "brew:ripgrep".
  3. Pick a name not in the reserved list: apk, apt, brew, brew-cask, dnf, flatpak, flatpak-user, mas, pacman.
  4. If the colliding plugin was already partially registered, run `mise plugin remove <name>` to clean up before retrying with the new name.

Example fix

# before
mise plugin add apt https://github.com/acme/apt-package-plugin
# after
mise plugin add acme-apt https://github.com/acme/apt-package-plugin

# or, if the goal is installing OS packages, skip the plugin entirely:
# mise.toml
[packages]
"apt:htop" = "3.3.0"
Defensive patterns

Strategy: validation

Validate before calling

#!/usr/bin/env bash
name="$1"
reserved="apk apt brew brew-cask dnf flatpak flatpak-user mas pacman"
case " $reserved " in
  *" $name "*) echo "error: '$name' collides with a built-in package manager" >&2; exit 1 ;;
esac
mise plugin add "$name" "${@:2}"

Try / catch

In scripts, capture stderr and exit code of `mise plugin add`; on non-zero exit, grep stderr for 'collides with a built-in package manager' and surface a rename hint instead of retrying the same name.

Prevention

When it happens

Trigger: Running `mise plugin add <name> <repo>` (or `mise plugins install`) where the plugin resolves to a package plugin (e.g. it declares a mise.plugin.toml package interface) and its name is exactly one of apk/apt/brew/brew-cask/dnf/flatpak/flatpak-user/mas/pacman. The failure happens post-clone, before install_state::add_plugin and backend::remove run, so no residual plugin state is kept.

Common situations: Writing a custom package-manager plugin and naming it after the OS manager it wraps (e.g. an 'apt' plugin for a Debian derivative); forking an existing package plugin and keeping the colliding repo name; migrating a config that previously used a community 'brew' plugin before brew became built-in.

Related errors


AI-assisted analysis of jdx/mise@9dcfcaa0dc (2026-08-17). Data as JSON: /api/errors/d35440e4a61deff1. Report an issue: GitHub.