jdx/mise · error

absent bootstrap group

Error message

absent bootstrap group '{name}' must not set gid or system

What it means

When a bootstrap group is declared with state = "absent", the group only needs its name — mise just removes it if it exists. Setting gid or system alongside "absent" is contradictory (there is no GID or system status for a group that should not exist), so from_toml rejects the config eagerly. This is a config-validation error raised before any system mutation.

Solutions

  1. Remove the gid and system keys from the absent group entry in mise.toml
  2. If you intended the group to exist, change state to "present" instead of removing the fields
  3. Regenerate the entry from the mise bootstrap plan/docs schema to see valid fields for absent state

Example fix

# before
[bootstrap.groups]
legacy-app = { state = "absent", gid = 1500, system = true }

# after
[bootstrap.groups]
legacy-app = { state = "absent" }
Defensive patterns

Strategy: validation

Validate before calling

# validate all absent groups carry no gid/system before running mise
tomlq -r '.bootstrap.groups | to_entries[] | select(.value.state == "absent") | select(has("gid") or has("system")) | .key' mise.toml

Prevention

When it happens

Trigger: A [bootstrap.groups] entry with state = "absent" that also specifies gid = N or system = true; a config converted from "present" to "absent" without deleting the now-meaningless fields.

Common situations: Decommissioning a group: flipping state to absent but leaving gid/system in place; copy-pasting a present-group stanza and only changing state; template-generated configs where fields are always emitted.

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


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

Appendix: source

Thrown at src/system/accounts.rs:202

        .map(|(name, config)| GroupRequest::from_toml(name, config))
        .collect::<Result<Vec<_>>>()?;
    let users = users
        .into_iter()
        .map(|(name, config)| UserRequest::from_toml(name, config))
        .collect::<Result<Vec<_>>>()?;
    validate_requests(&groups, &users)?;
    Ok(AccountRequests { groups, users })
}

pub(crate) fn prepare_requests_from_config(config: &Config) -> Result<AccountRequests> {
    requests_from_config(config)
}

impl GroupRequest {
    fn from_toml(name: String, config: GroupTomlConfig) -> Result<Self> {
        validate_name("group", &name)?;
        if config.state == AccountState::Absent && (config.gid.is_some() || config.system) {
            bail!("absent bootstrap group '{name}' must not set gid or system");
        }
        let inspection = match nix::unistd::Group::from_name(&name)? {
            Some(group) => {
                let gid = group.gid.as_raw();
                let desired_gid_owner = match config.gid.filter(|desired| *desired != gid) {
                    Some(desired) => {
                        nix::unistd::Group::from_gid(nix::unistd::Gid::from_raw(desired))?
                            .map(|group| group.name)
                    }
                    None => None,
                };
                GroupInspection::Present {
                    gid,
                    desired_gid_owner,
                }
            }
            None => match config.gid {
                Some(gid) => match nix::unistd::Group::from_gid(nix::unistd::Gid::from_raw(gid))? {

View on GitHub (pinned to 533346cc37)