jdx/mise · error
{name} does not support declarative package removal
Error message
{name} does not support declarative package removal What it means
During `mise system packages install`, the driver computes `remove_targets`: packages whose desired state is `Absent` (declarative removal). If removal targets exist but the manager's `supports_remove()` returns false, the operation cannot honor the declarative spec and mise bails rather than silently leaving packages installed.
Source
Thrown at src/cli/system/driver.rs:187
let installed = statuses
.iter()
.filter(|status| status.request.desired == PackageDesiredState::Present)
.filter(|status| status.state.is_installed())
.count();
if action == Action::Install && installed > 0 {
info!("{name}: {installed} package(s) already installed");
}
let already_absent = statuses
.iter()
.filter(|status| status.request.desired == PackageDesiredState::Absent)
.filter(|status| matches!(status.state, PackageState::Missing))
.count();
if action == Action::Install && already_absent > 0 {
info!("{name}: {already_absent} package(s) already absent");
}
if !remove_targets.is_empty() {
if !mp.manager.supports_remove() {
bail!("{name} does not support declarative package removal");
}
let remove = remove_targets
.iter()
.map(|status| status.request.clone())
.collect::<Vec<_>>();
let list = remove
.iter()
.map(|request| request.to_string())
.collect::<Vec<_>>();
if !d.dry_run && !d.yes && console::user_attended_stderr() {
let msg = format!("{name}: remove {}?", list.join(", "));
if !prompt::confirm(msg)?.is_yes() {
info!("{name}: removal skipped");
} else {
mp.manager.remove(&remove, &opts).await?;
info!("{name}: removed {}", list.join(", "));
}
} else {View on GitHub (pinned to afd2eddd3a)
Solutions
- Implement `hooks/package_uninstall.lua` (or the remove hook) in the plugin so it supports removal.
- Remove the absent-marked package entries from the config, or uninstall those packages manually.
- Use a different manager that supports removal for those packages.
- Run with --dry-run to see which targets would be removed before adjusting config.
Example fix
// before (mise.toml) [system_packages] "myplugin:legacy-tool" = false // after: remove the entry and uninstall manually, or switch manager [system_packages] "brew:legacy-tool" = false
Defensive patterns
Strategy: validation
Validate before calling
# Only mark packages absent for managers that support removal # confirm with a dry run listing remove targets mise system packages --dry-run
Prevention
- Implement hooks/package_uninstall.lua in custom plugins before using absent states.
- Avoid `manager:pkg = false` entries for minimal install-only plugins.
- Use --dry-run to detect remove targets early.
When it happens
Trigger: A system_packages config (or tracked config files) marks a package as absent (`manager:pkg = false` / absent desired state) while the resolved manager plugin lacks a package-remove hook (`supports_remove() == false`).
Common situations: Writing `"plugin:foo" = false` for a minimal vfox plugin that only implements install hooks; sharing a config across machines where the plugin variant differs; expecting `system packages install` to uninstall for a manager that only supports install.
Understand the failure class
Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.
Related errors
- package manager '{}' does not support pruning
- package plugin '{}' does not support uninstall; add hooks/pa
- package plugin '{plugin_name}' is not a tool backend
- manager '{only}' is excluded by the system_packages.managers
- no packages requested for manager '{only}'
AI-assisted analysis of jdx/mise@afd2eddd3a (2026-09-09).
Data as JSON: /api/errors/31dd225946f14e20.
Report an issue: GitHub.