jdx/mise · error
refusing unsafe change to bootstrap group '{}'; inspect `mis
Error message
refusing unsafe change to bootstrap group '{}'; inspect `mise bootstrap plan` What it means
GroupRequest::action() converts the computed plan into an action; when the plan's ResourceAction is Unknown — mise cannot reconcile desired vs. current group state safely (for example the desired gid is already owned by a different group name, an IdCollision, while you want the group present) — it refuses to act and directs you to `mise bootstrap plan` for the details. This is a deliberate safety stop before any privileged groupmod/groupadd/groupdel.
Source
Thrown at src/system/accounts.rs:309
),
(GroupInspection::IdCollision { gid, name }, AccountState::Present) => {
ResourcePlan::new(
id,
format!("absent; gid {gid} belongs to {name}"),
desired,
ResourceAction::Unknown,
)
}
(GroupInspection::IdCollision { .. }, AccountState::Absent) => {
ResourcePlan::new(id, "absent", desired, ResourceAction::Noop)
}
}
}
fn action(&self) -> Result<Option<AccountAction>> {
match self.plan().action {
ResourceAction::Noop => Ok(None),
ResourceAction::Unknown => bail!(
"refusing unsafe change to bootstrap group '{}'; inspect `mise bootstrap plan`",
self.name
),
ResourceAction::Create => Ok(Some(AccountAction::CreateGroup {
name: self.name.clone(),
gid: self.gid,
system: self.system,
})),
ResourceAction::Update => Ok(Some(AccountAction::UpdateGroup {
name: self.name.clone(),
gid: self.gid.expect("group update requires a desired gid"),
})),
ResourceAction::Remove => Ok(Some(AccountAction::RemoveGroup {
name: self.name.clone(),
})),
}
}
}View on GitHub (pinned to 9dcfcaa0dc)
Solutions
- Run `mise bootstrap plan` and read the reported current/desired state for the named group.
- Resolve the collision manually: free the gid (remove/re-gid the other group) or pick a different gid in config.
- If the group should not be managed at all, drop it from [bootstrap.groups].
- Re-run plan until the action is a plain create/update/remove, then apply.
Example fix
# before: gid 1005 already owned by group 'oldteam' [bootstrap.groups.deploy] state = "present" gid = 1005 # after: choose a free gid, or remove the old group first [bootstrap.groups.deploy] state = "present" gid = 1010
Defensive patterns
Strategy: validation
Validate before calling
# always plan before apply; refuse to apply when any action is unknown out=$(mise bootstrap plan) if grep -q 'refusing unsafe change' <<<"$out"; then echo "$out" >&2; exit 1 fi mise bootstrap apply
Try / catch
Treat this bail as a hard stop: capture the group name from the message, run `mise bootstrap plan`, and resolve the gid/state collision; never script a retry of apply without changing state.
Prevention
- Make `mise bootstrap plan` a required pre-apply gate in automation.
- Allocate gids from a documented range to avoid collisions with system groups.
- Inspect unfamiliar hosts with plan before the first apply.
When it happens
Trigger: Bootstrap apply (or anything calling action()) where a group's desired state produces Unknown: typically gid collisions (two names claiming one gid), or inspected current state that fits no safe create/update/remove transition. `mise bootstrap plan` shows the same Unknown action with the diff.
Common situations: Reusing a gid that another system group already holds; importing hosts whose group database drifted from config; renaming groups while keeping gids; running apply before plan on an unfamiliar machine.
Related errors
- refusing unsafe change to bootstrap user '{}'; inspect `mise
- bootstrap plan contains resources with unknown state
- absent bootstrap group '{name}' must not set gid or system
- present bootstrap user '{name}' requires a primary group
- bootstrap user '{name}' sets exclusive_groups without groups
AI-assisted analysis of jdx/mise@9dcfcaa0dc (2026-08-17).
Data as JSON: /api/errors/22ebb8db29de53ae.
Report an issue: GitHub.