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

  1. Run `mise bootstrap plan` and read the reported current/desired state for the named group.
  2. Resolve the collision manually: free the gid (remove/re-gid the other group) or pick a different gid in config.
  3. If the group should not be managed at all, drop it from [bootstrap.groups].
  4. 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

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


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