{"record":{"id":"2a58dc0ea0368e13","repo":"jdx/mise","slug":"absent-bootstrap-group-name-must-not-set-gid-o","errorCode":null,"errorMessage":"absent bootstrap group '{name}' must not set gid or system","messagePattern":"absent bootstrap group '(.+?)' must not set gid or system","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/system/accounts.rs","lineNumber":202,"sourceCode":"        .map(|(name, config)| GroupRequest::from_toml(name, config))\n        .collect::<Result<Vec<_>>>()?;\n    let users = users\n        .into_iter()\n        .map(|(name, config)| UserRequest::from_toml(name, config))\n        .collect::<Result<Vec<_>>>()?;\n    validate_requests(&groups, &users)?;\n    Ok(AccountRequests { groups, users })\n}\n\npub fn prepare_requests_from_config(config: &Config) -> Result<AccountRequests> {\n    requests_from_config(config)\n}\n\nimpl GroupRequest {\n    fn from_toml(name: String, config: GroupTomlConfig) -> Result<Self> {\n        validate_name(\"group\", &name)?;\n        if config.state == AccountState::Absent && (config.gid.is_some() || config.system) {\n            bail!(\"absent bootstrap group '{name}' must not set gid or system\");\n        }\n        let inspection = match nix::unistd::Group::from_name(&name)? {\n            Some(group) => {\n                let gid = group.gid.as_raw();\n                let desired_gid_owner = match config.gid.filter(|desired| *desired != gid) {\n                    Some(desired) => {\n                        nix::unistd::Group::from_gid(nix::unistd::Gid::from_raw(desired))?\n                            .map(|group| group.name)\n                    }\n                    None => None,\n                };\n                GroupInspection::Present {\n                    gid,\n                    desired_gid_owner,\n                }\n            }\n            None => match config.gid {\n                Some(gid) => match nix::unistd::Group::from_gid(nix::unistd::Gid::from_raw(gid))? {","sourceCodeStart":184,"sourceCodeEnd":220,"githubUrl":"https://github.com/jdx/mise/blob/9dcfcaa0dc8747a2577d3270b69bb9d8313b2807/src/system/accounts.rs#L184-L220","documentation":"GroupRequest::from_toml validates that a group declared state = \"absent\" does not also carry gid = <n> or system = true. Removal requests are name-only: specifying a gid or the system flag for a group you are deleting is contradictory (and gid/system only make sense for creation), so config parsing fails fast with the offending group's name in the message.","triggerScenarios":"A mise.toml [bootstrap.groups.<name>] table containing state = \"absent\" together with gid = 1005 and/or system = true, loaded by `mise bootstrap plan`/`apply` (or any account-request build).","commonSituations":"Flipping a group from present to absent and leaving the old creation fields behind; copy-pasting a present-group template and only changing state; attempting to 'delete by gid' which mise does not support.","solutions":["Reduce the absent group entry to state = \"absent\" only.","If you meant to keep the group, set state = \"present\" and keep gid/system.","Re-run `mise bootstrap plan` to confirm the config now parses."],"exampleFix":"# before\n[bootstrap.groups.legacy]\nstate = \"absent\"\ngid = 1005\nsystem = true\n# after\n[bootstrap.groups.legacy]\nstate = \"absent\"","handlingStrategy":"validation","validationCode":"python3 - <<'EOF'\nimport sys, tomllib\ncfg = tomllib.load(open('mise.toml','rb'))\nfor name, g in cfg.get('bootstrap', {}).get('groups', {}).items():\n    if g.get('state') == 'absent' and ('gid' in g or g.get('system')):\n        sys.exit(f\"absent group '{name}' must not set gid or system\")\nEOF","typeGuard":"def absent_group_is_clean(g: dict) -> bool:\n    return not ('gid' in g or g.get('system')) if g.get('state') == 'absent' else True","tryCatchPattern":null,"preventionTips":["Treat state = \"absent\" entries as name-only by convention.","When flipping present -> absent, delete the creation fields, don't just change state.","Run `mise bootstrap plan` in CI to catch config errors before apply."],"tags":["mise","bootstrap","groups","config-validation","toml"],"backgroundTag":"config-validation-failed","analyzedSha":"9dcfcaa0dc8747a2577d3270b69bb9d8313b2807","analyzedAt":"2026-08-17T14:28:50.624Z","schemaVersion":2},"datasetVersion":"2026-08-21T13:17:26.733Z"}