{"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/533346cc374382b41ec5ff70536252b2e96e725c/src/system/accounts.rs#L335-L371","documentation":"exclusive_groups declares that the user's group memberships fully replace (not merge with) existing memberships. It is meaningless without a groups list, so mise rejects exclusive_groups=true when groups is unset. This catches configs that would either do nothing or ambiguously imply exclusive control over an empty membership set.","triggerScenarios":"Setting exclusive_groups = true on a bootstrap user while omitting the groups field.","commonSituations":"Copy-pasting a user entry and deleting the groups list while leaving exclusive_groups enabled; converting an existing user to exclusive management but forgetting to enumerate the target groups.","solutions":["Add a groups list alongside exclusive_groups = true.","Remove exclusive_groups (set it to false or delete it) if you do not intend full replacement of memberships.","Run `mise bootstrap plan` to review the intended group changes before re-running."],"exampleFix":"// before\n[[bootstrap.users]]\nname = \"deploy\"\nexclusive_groups = true\n\n// after\n[[bootstrap.users]]\nname = \"deploy\"\nexclusive_groups = true\ngroups = [\"deploy\", \"docker\"]","handlingStrategy":"validation","validationCode":"function validateExclusiveGroups(user) {\n  if (user.exclusive_groups && !Array.isArray(user.groups)) {\n    throw new Error(`user '${user.name}': exclusive_groups requires a groups list`);\n  }\n}","typeGuard":"function hasGroupsWhenExclusive(user) {\n  return !user.exclusive_groups || Array.isArray(user.groups) && user.groups.length > 0;\n}","tryCatchPattern":"try {\n  await mise.bootstrap.apply(config);\n} catch (e) {\n  if (String(e).includes('exclusive_groups without groups')) {\n    console.error('Add a groups list or drop exclusive_groups:', e.message);\n  } else throw e;\n}","preventionTips":["Always pair exclusive_groups with an explicit groups array.","Schema-validate bootstrap TOML before applying.","Review `mise bootstrap plan` diff to confirm replacement memberships are intended."],"tags":["bootstrap","groups","config-validation"],"backgroundTag":"missing-required-config-field","analyzedSha":"533346cc374382b41ec5ff70536252b2e96e725c","analyzedAt":"2026-09-17T13:35:38.149Z","contentChangedAt":"2026-09-17T13:35:38.149Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}