{"record":{"id":"7cb5cd267089553c","repo":"jdx/mise","slug":"program-failed-with-status","errorCode":null,"errorMessage":"{program} failed with {status}","messagePattern":"(.+?) failed with (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/system/accounts.rs","lineNumber":1012,"sourceCode":"                    args.push(\"--remove\".to_string());\n                }\n                args.push(name);\n                run_account_command(\"userdel\", &args)\n            }\n        }\n    }\n}\n\nfn run_account_command(program: &str, args: &[String]) -> Result<()> {\n    let path = [\"/usr/sbin\", \"/usr/bin\", \"/sbin\", \"/bin\"]\n        .iter()\n        .map(|dir| PathBuf::from(dir).join(program))\n        .find(|path| path.is_file())\n        .ok_or_else(|| eyre!(\"required account command '{program}' was not found\"))?;\n    info!(\"$ {} {}\", path.display(), args.join(\" \"));\n    let status = Command::new(&path).args(args).status()?;\n    if !status.success() {\n        bail!(\"{program} failed with {status}\");\n    }\n    Ok(())\n}\n\n#[cfg(test)]\nmod tests {\n    use super::*;\n\n    #[test]\n    fn validates_account_names() {\n        assert!(validate_name(\"user\", \"mise-cache_1\").is_ok());\n        assert!(validate_name(\"user\", \"1invalid\").is_err());\n        assert!(validate_name(\"user\", \"-invalid\").is_err());\n        assert!(validate_name(\"group\", \"invalid/name\").is_err());\n        assert!(validate_name(\"group\", &\"a\".repeat(33)).is_err());\n    }\n\n    #[test]","sourceCodeStart":994,"sourceCodeEnd":1030,"githubUrl":"https://github.com/jdx/mise/blob/9dcfcaa0dc8747a2577d3270b69bb9d8313b2807/src/system/accounts.rs#L994-L1030","documentation":"`run_account_command` locates account-management binaries (`useradd`, `groupadd`, `usermod`, `userdel`, ...) in `/usr/sbin`, `/usr/bin`, `/sbin`, `/bin`, logs the full command at info level, and runs it. If the child exits non-zero, mise bails with the program name and `ExitStatus`; the child's own stderr (printed to the terminal) carries the real diagnosis.","triggerScenarios":"Converging accounts when the underlying tool fails: `useradd` exits non-zero because the requested `uid` is already in use, the home directory exists, or the primary group is missing; `userdel` fails because the user is logged in; `usermod` fails because a supplementary group does not exist.","commonSituations":"Hard-coding a uid/gid that collides with an existing account; removing a user with active sessions; referencing a `[bootstrap.groups]` entry that was renamed or ordered after first use; minimal containers missing shadow-utils (then a different error, 'required account command ... was not found', fires instead).","solutions":["Find the logged command line (mise prints `$ /usr/sbin/useradd ...` at info level) and run it manually as root to see its stderr.","Fix the reported conflict: drop or change the colliding `uid`/`gid`, close the user's sessions before removal, or declare the missing group in `[bootstrap.groups]`.","Re-run `mise bootstrap accounts apply` (with `--dry-run` first if you want to re-check the plan)."],"exampleFix":"# before\n[bootstrap.users.builder]\ngroup = \"builder\"\nuid = 1005   # already taken on this host -> useradd exits non-zero\n\n# after\n[bootstrap.users.builder]\ngroup = \"builder\"   # let useradd pick a free uid","handlingStrategy":"try-catch","validationCode":"// preflight: ensure the requested ids are actually free\nfn uid_free(uid: u32) -> bool {\n    // read /etc/passwd and check no entry claims uid\n    std::fs::read_to_string(\"/etc/passwd\").map(|p| {\n        !p.lines().any(|l| l.split(':').nth(2) == Some(&uid.to_string()))\n    }).unwrap_or(false)\n}","typeGuard":null,"tryCatchPattern":"match accounts::apply(&requests, dry_run, yes) {\n    Ok(changed) => { /* report */ }\n    Err(err) if err.to_string().contains(\"failed with\") => {\n        // terminal: program + exit status named; child stderr already printed.\n        // Re-run the logged `$ /usr/sbin/<prog> ...` line as root for detail,\n        // fix the conflict (uid/gid collision, missing group, logged-in user), retry once.\n        return Err(err);\n    }\n    Err(err) => return Err(err),\n}","preventionTips":["Prefer letting useradd pick ids (omit uid/gid) instead of pinning values that collide.","Declare every referenced group in [bootstrap.groups] before users that use it.","Run `mise bootstrap accounts apply --dry-run` first and read the planned command lines."],"tags":["mise","bootstrap","accounts","subprocess","useradd","exit-status"],"backgroundTag":"subprocess-nonzero-exit","analyzedSha":"9dcfcaa0dc8747a2577d3270b69bb9d8313b2807","analyzedAt":"2026-08-17T14:28:50.624Z","schemaVersion":2},"datasetVersion":"2026-08-21T13:17:26.733Z"}