{"record":{"id":"5246644b0b3a251d","repo":"jdx/mise","slug":"bootstrap-user-name-sets-exclusive-groups-with","errorCode":null,"errorMessage":"bootstrap user '{name}' sets exclusive_groups without groups","messagePattern":"bootstrap user '(.+?)' sets exclusive_groups without groups","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/system/accounts.rs","lineNumber":353,"sourceCode":"        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\n            .as_ref()\n            .is_some_and(|comment| comment.contains([':', '\\n', '\\r']))\n        {","sourceCodeStart":335,"sourceCodeEnd":371,"githubUrl":"https://github.com/jdx/mise/blob/9dcfcaa0dc8747a2577d3270b69bb9d8313b2807/src/system/accounts.rs#L335-L371","documentation":"UserRequest::from_toml rejects a user that sets exclusive_groups = true without also setting groups. exclusive_groups means 'usergroup membership is exactly this list' (replaces supplementary groups), so without a groups list there is nothing to be exclusive over and the semantics are undefined; parsing fails with the user's name.","triggerScenarios":"A [bootstrap.users.<name>] table with exclusive_groups = true but no groups = [...] array, loaded during bootstrap config parsing.","commonSituations":"Intending 'remove the user from all extra groups' and assuming exclusive_groups alone does that; splitting a config and dropping the groups line; renaming the groups key (e.g. to extra_groups) so it no longer parses.","solutions":["Add an explicit groups list that the user should be exclusive to, e.g. groups = [\"deploy\"].","If you want the user removed from supplementary groups, list the exact remaining groups (possibly just the primary one's companions) — mise has no 'empty list' shorthand beyond an explicit empty array, so confirm behavior with `mise bootstrap plan`.","If exclusivity was unintended, delete exclusive_groups."],"exampleFix":"# before\n[bootstrap.users.ci]\nstate = \"present\"\ngroup = \"ci\"\nexclusive_groups = true\n# after\n[bootstrap.users.ci]\nstate = \"present\"\ngroup = \"ci\"\nexclusive_groups = true\ngroups = [\"docker\"]","handlingStrategy":"validation","validationCode":"python3 - <<'EOF'\nimport sys, tomllib\ncfg = tomllib.load(open('mise.toml','rb'))\nfor name, u in cfg.get('bootstrap', {}).get('users', {}).items():\n    if u.get('exclusive_groups') and 'groups' not in u:\n        sys.exit(f\"user '{name}' sets exclusive_groups without groups\")\nEOF","typeGuard":"def exclusive_groups_valid(u: dict) -> bool:\n    return ('groups' in u) if u.get('exclusive_groups') else True","tryCatchPattern":null,"preventionTips":["Treat exclusive_groups and groups as a pair that always travel together.","Review the planned membership in `mise bootstrap plan` output before apply."],"tags":["mise","bootstrap","users","config-validation","groups"],"backgroundTag":"config-validation-failed","analyzedSha":"9dcfcaa0dc8747a2577d3270b69bb9d8313b2807","analyzedAt":"2026-08-17T14:28:50.624Z","schemaVersion":2},"datasetVersion":"2026-08-21T13:17:26.733Z"}