jdx/mise · error

refusing unsafe change to bootstrap user

Error message

refusing unsafe change to bootstrap user '{}'; inspect `mise bootstrap plan`

What it means

When applying bootstrap changes, if the computed plan for a user yields ResourceAction::Unknown, mise refuses to proceed rather than guess at a destructive change. 'Unknown' means the live system state could not be reconciled with the declaration (e.g. ambiguous user state), so the safe behavior is to bail and ask the operator to inspect the plan.

Solutions

  1. Run `mise bootstrap plan` and read the reported action for the offending user.
  2. Reconcile the live account state manually (userdel/usermod) so the plan becomes Create/Remove/Noop.
  3. Align the declaration (state and attributes) with the actual system state, then re-apply.
Defensive patterns

Strategy: try-catch

Validate before calling

const plan = await mise.bootstrap.plan(config);
const unsafe = plan.users.filter((u) => u.action === 'unknown');
if (unsafe.length) throw new Error(`Unsafe plan for users: ${unsafe.map((u) => u.name).join(', ')}`);

Try / catch

try {
  await mise.bootstrap.apply(config);
} catch (e) {
  if (String(e).includes('refusing unsafe change to bootstrap user')) {
    console.error('Inspect `mise bootstrap plan`, reconcile the live account, then retry.');
  } else throw e;
}

Prevention

When it happens

Trigger: Running `mise bootstrap apply` (or similar) when a declared user's computed plan action is Unknown — typically due to inconsistent or unverifiable live system state for that account.

Common situations: Manual edits to /etc/passwd leaving a user in a state mise cannot classify; a user declared absent but detected present with unmanaged attributes; partially failed prior bootstrap runs.

Understand the failure class

Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.

Related errors


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

Appendix: source

Thrown at src/system/accounts.rs:546

                groups.iter().cloned().collect::<Vec<_>>().join(",")
            ));
        }
        if let Some(home) = &self.home {
            parts.push(format!("home {}", home.display()));
        }
        if let Some(shell) = &self.shell {
            parts.push(format!("shell {}", shell.display()));
        }
        if let Some(comment) = &self.comment {
            parts.push(format!("comment {comment}"));
        }
        parts.join("; ")
    }

    fn action(&self) -> Result<Option<AccountAction>> {
        match self.plan().action {
            ResourceAction::Noop => Ok(None),
            ResourceAction::Unknown => bail!(
                "refusing unsafe change to bootstrap user '{}'; inspect `mise bootstrap plan`",
                self.name
            ),
            ResourceAction::Create => Ok(Some(AccountAction::CreateUser {
                name: self.name.clone(),
                uid: self.uid,
                group: self
                    .group
                    .clone()
                    .expect("present user has a primary group"),
                groups: self
                    .groups
                    .as_ref()
                    .map(|groups| groups.iter().cloned().collect())
                    .unwrap_or_default(),
                home: self.home.clone(),
                shell: self.shell.clone(),
                comment: self.comment.clone(),

View on GitHub (pinned to 533346cc37)