{"record":{"id":"8e89f13841b3c347","repo":"jdx/mise","slug":"absent-bootstrap-user-name-may-only-set-state","errorCode":null,"errorMessage":"absent bootstrap user '{name}' may only set state and remove_home","messagePattern":"absent bootstrap user '(.+?)' may only set state and remove_home","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/system/accounts.rs","lineNumber":350,"sourceCode":"        if config.state == AccountState::Present && config.group.is_none() {\n            bail!(\"present bootstrap user '{name}' requires a primary group\");\n        }\n        if config.state == AccountState::Present && config.remove_home {\n            bail!(\"present bootstrap user '{name}' must not set remove_home\");\n        }\n        if config.state == AccountState::Absent\n            && (config.uid.is_some()\n                || config.group.is_some()\n                || config.groups.is_some()\n                || config.exclusive_groups\n                || config.home.is_some()\n                || config.shell.is_some()\n                || config.comment.is_some()\n                || config.system\n                || config.create_home.is_some()\n                || config.move_home)\n        {\n            bail!(\"absent bootstrap user '{name}' may only set state and remove_home\");\n        }\n        if config.exclusive_groups && config.groups.is_none() {\n            bail!(\"bootstrap user '{name}' sets exclusive_groups without groups\");\n        }\n        if config.move_home && config.home.is_none() {\n            bail!(\"bootstrap user '{name}' sets move_home without home\");\n        }\n        if let Some(group) = &config.group {\n            validate_name(\"group\", group)?;\n        }\n        if let Some(path) = &config.home {\n            validate_account_path(&name, \"home\", path)?;\n        }\n        if let Some(path) = &config.shell {\n            validate_account_path(&name, \"shell\", path)?;\n        }\n        if config\n            .comment","sourceCodeStart":332,"sourceCodeEnd":368,"githubUrl":"https://github.com/jdx/mise/blob/9dcfcaa0dc8747a2577d3270b69bb9d8313b2807/src/system/accounts.rs#L332-L368","documentation":"UserRequest::from_toml enforces that an absent user (state = \"absent\") may configure nothing except state and remove_home. If any of uid, group, groups, exclusive_groups, home, shell, comment, system, create_home, or move_home is set on an absent user, parsing bails. Deletion requests are name-only by design, so leftover creation attributes are treated as a config error rather than silently ignored.","triggerScenarios":"A [bootstrap.users.<name>] table with state = \"absent\" that also sets e.g. uid = 1200, shell = \"/bin/bash\", or groups = [...], while `mise bootstrap` loads the config.","commonSituations":"Converting a fully-specified present user to absent by changing only the state field; deprovisioning configs generated from provisioning templates; merging config layers where an absent entry inherits extra keys.","solutions":["Strip the absent user's table down to state = \"absent\" (plus remove_home = true only if the home directory should be deleted).","If the attributes are needed, the user should be state = \"present\" instead.","Re-run `mise bootstrap plan` to verify."],"exampleFix":"# before\n[bootstrap.users.oldsvc]\nstate = \"absent\"\nuid = 900\nshell = \"/usr/sbin/nologin\"\n# after\n[bootstrap.users.oldsvc]\nstate = \"absent\"\nremove_home = true","handlingStrategy":"validation","validationCode":"python3 - <<'EOF'\nimport sys, tomllib\nABSENT_OK = {'state', 'remove_home'}\ncfg = tomllib.load(open('mise.toml','rb'))\nfor name, u in cfg.get('bootstrap', {}).get('users', {}).items():\n    if u.get('state') == 'absent' and set(u) - ABSENT_OK:\n        extra = sorted(set(u) - ABSENT_OK)\n        sys.exit(f\"absent user '{name}' sets disallowed keys: {extra}\")\nEOF","typeGuard":"ABSENT_ALLOWED = {'state', 'remove_home'}\ndef absent_user_is_name_only(u: dict) -> bool:\n    return set(u) <= ABSENT_ALLOWED if u.get('state') == 'absent' else True","tryCatchPattern":null,"preventionTips":["Author absent-user entries from scratch rather than editing present ones.","Keep deprovisioning and provisioning in separate config files.","Run `mise bootstrap plan` as a lint step."],"tags":["mise","bootstrap","users","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"}