jdx/mise · error

failed with

Error message

{program} failed with {status}

What it means

This error is raised by the account command runner in src/system/accounts.rs when an external command required to manage users/groups (e.g. useradd, groupadd, usermod) exits with a non-zero status. The runner locates the program on PATH, executes it, and translates any failure exit code into this error including the program name and its exit Status. It wraps all failures of the privileged account tooling into one message.

Solutions

  1. Read the full stderr from the failed command (run with debug logging: MISE_DEBUG=1) to see the account tool's actual complaint.
  2. Ensure the apply step runs as root (sudo) so account tools can modify /etc/passwd and /etc/group.
  3. Make the plan idempotent or reconcile pre-existing users/groups with the same GID/UID before applying.
  4. Fix the offending group/user definition in the [bootstrap] config (invalid names, duplicate GIDs, bad home dirs).

Example fix

// before
sudo mise bootstrap apply   # fails: useradd failed with exit status 9 (user exists)
// after
# either remove the existing conflicting user or align the plan
sudo usermod -g developers deploy && sudo mise bootstrap apply
Defensive patterns

Strategy: try-catch

Validate before calling

for prog in ["useradd", "groupadd"] {
    if which(prog).is_none() {
        return Err(format!("required account command '{prog}' was not found"));
    }
}
if !nix::unistd::Uid::effective().is_root() {
    return Err("account commands require root".into());
}

Type guard

fn ran_successfully(status: &std::process::ExitStatus) -> bool { status.success() }

Try / catch

match run_account_program("useradd", &args) {
    Err(e) if e.to_string().contains("failed with") => {
        // capture stderr, check for 'already exists' / permission denied and reconcile
        eprintln!("account command failed: {e}");
    }
    Err(e) => return Err(e),
    Ok(()) => {}
}

Prevention

When it happens

Trigger: Running bootstrap user/group apply where the invoked account command (useradd/groupadd/etc.) returns non-zero — e.g. group already exists, invalid option values, insufficient privileges, or the backend rejecting a username.

Common situations: Applying a bootstrap plan where the group or user already exists with conflicting attributes; running without root so the account command is denied; a config-derived group name violating system constraints; partial prior apply leaving inconsistent state.

Related errors


AI-assisted analysis of jdx/mise@533346cc37 (2026-09-17). Data as JSON: /api/errors/7cb5cd267089553c. Report an issue: GitHub.

Appendix: source

Thrown at src/system/accounts.rs:1013

                    args.push("--remove".to_string());
                }
                args.push(name);
                run_account_command("userdel", &args)
            }
        }
    }
}

fn run_account_command(program: &str, args: &[String]) -> Result<()> {
    let path = ["/usr/sbin", "/usr/bin", "/sbin", "/bin"]
        .iter()
        .map(|dir| PathBuf::from(dir).join(program))
        .find(|path| path.is_file())
        .ok_or_else(|| eyre!("required account command '{program}' was not found"))?;
    info!("$ {} {}", path.display(), args.join(" "));
    let status = Command::new(&path).args(args).status()?;
    if !status.success() {
        bail!("{program} failed with {status}");
    }
    Ok(())
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn validates_account_names() {
        assert!(validate_name("user", "mise-cache_1").is_ok());
        assert!(validate_name("user", "1invalid").is_err());
        assert!(validate_name("user", "-invalid").is_err());
        assert!(validate_name("group", "invalid/name").is_err());
        assert!(validate_name("group", &"a".repeat(33)).is_err());
    }

    #[test]

View on GitHub (pinned to 533346cc37)