jdx/mise · error
absent bootstrap user
Error message
absent bootstrap user '{name}' may only set state and remove_home What it means
When a bootstrap user is declared with state=absent, mise only allows configuring the user's state and remove_home; all other user attributes (shell, comment, uid/gid, groups, system, create_home, move_home, home, etc.) are rejected. This prevents silently configuring properties of a user that will not exist. The check runs during bootstrap plan validation in src/system/accounts.rs.
Solutions
- Strip all attribute fields from the user entry, keeping only state (and remove_home if desired).
- If you actually want the user configured, remove state="absent" so the fields are meaningful.
- Run `mise bootstrap plan` to confirm which fields triggered the rejection.
Example fix
// before [[bootstrap.users]] name = "svc" state = "absent" shell = "/usr/sbin/nologin" groups = ["docker"] // after [[bootstrap.users]] name = "svc" state = "absent" remove_home = true
Defensive patterns
Strategy: validation
Validate before calling
function validateAbsentUser(user) {
const allowed = new Set(['name', 'state', 'remove_home']);
if (user.state === 'absent') {
const extra = Object.keys(user).filter((k) => !allowed.has(k));
if (extra.length) throw new Error(`absent user sets fields: ${extra.join(', ')}`);
}
} Type guard
function isAbsentOnlyUser(user) {
return user.state === 'absent' &&
Object.keys(user).every((k) => ['name', 'state', 'remove_home'].includes(k));
} Try / catch
try {
await mise.bootstrap.apply(config);
} catch (e) {
if (String(e).includes("may only set state and remove_home")) {
console.error('Prune attribute fields from absent-user entries:', e.message);
} else throw e;
} Prevention
- Keep absent-user entries minimal: name, state, remove_home only.
- Never reuse a single user block for both present and absent states — define separate entries.
- Run `mise bootstrap plan` in CI before applying.
When it happens
Trigger: Declaring a bootstrap user with state="absent" while also setting any of: shell, comment, uid/gid, system=true, create_home, move_home, home, groups, or exclusive_groups.
Common situations: Reusing one TOML user block for both 'create this user' and 'remove that user' by only flipping state to absent; refactoring a previously-present user entry to absent without pruning its attribute fields; copy-pasting a present-user definition and adding state="absent".
Understand the failure class
Background: Conflicting config options: "cannot be used together" — configuration validation errors across open-source libraries — this error's family across 162 libraries.
Related errors
- absent bootstrap group
- bootstrap user ' ' sets exclusive_groups without groups
- bootstrap user ' ' sets move_home without home
- present bootstrap user
- present bootstrap user
AI-assisted analysis of jdx/mise@533346cc37 (2026-09-17).
Data as JSON: /api/errors/8e89f13841b3c347.
Report an issue: GitHub.
Appendix: source
Thrown at src/system/accounts.rs:350
if config.state == AccountState::Present && config.group.is_none() {
bail!("present bootstrap user '{name}' requires a primary group");
}
if config.state == AccountState::Present && config.remove_home {
bail!("present bootstrap user '{name}' must not set remove_home");
}
if config.state == AccountState::Absent
&& (config.uid.is_some()
|| config.group.is_some()
|| config.groups.is_some()
|| config.exclusive_groups
|| config.home.is_some()
|| config.shell.is_some()
|| config.comment.is_some()
|| config.system
|| config.create_home.is_some()
|| config.move_home)
{
bail!("absent bootstrap user '{name}' may only set state and remove_home");
}
if config.exclusive_groups && config.groups.is_none() {
bail!("bootstrap user '{name}' sets exclusive_groups without groups");
}
if config.move_home && config.home.is_none() {
bail!("bootstrap user '{name}' sets move_home without home");
}
if let Some(group) = &config.group {
validate_name("group", group)?;
}
if let Some(path) = &config.home {
validate_account_path(&name, "home", path)?;
}
if let Some(path) = &config.shell {
validate_account_path(&name, "shell", path)?;
}
if config
.commentView on GitHub (pinned to 533346cc37)