jdx/mise · error · eyre::Report
{} failed
Error message
{} failed What it means
sudo::run executes an elevated command via sudo (with a pre_exec fchdir restoring the caller's cwd) and checks the exit status; on failure it bails with the full argv, which includes env assignments injected by the wrapper. Interactive callers are expected to hold a sudo timestamp from a prior `sudo -v`, so a failure here means sudoers policy rejected the command or the elevated command itself exited non-zero.
Source
Thrown at src/system/sudo.rs:157
let raw = dir.as_fd().as_raw_fd();
let mut cmd = Command::new(&argv[0]);
cmd.args(&argv[1..]);
// SAFETY: `fchdir` is async-signal-safe and only alters the child's working
// directory. `raw` stays open in the parent across the spawn, and CLOEXEC
// (if set) only takes effect at exec, after pre_exec has run.
unsafe {
cmd.pre_exec(move || {
if nix::libc::fchdir(raw) == -1 {
return Err(std::io::Error::last_os_error());
}
Ok(())
});
}
let status = cmd
.status()
.wrap_err_with(|| format!("failed to run {}", argv.join(" ")))?;
if !status.success() {
bail!("{} failed", argv.join(" "));
}
Ok(())
}
/// Run an elevated command and capture its output.
///
/// Interactive callers authenticate with an inherited `sudo -v` first so a
/// password prompt is never hidden inside captured stderr. Non-interactive
/// callers retain [`ensure_elevation_available`]'s fail-fast `sudo -n` check.
pub(crate) fn output(program: &str, args: &[String], envs: &[(String, String)]) -> Result<Output> {
let argv = argv_with_env(program, args, envs);
let manual_cmd = std::iter::once("sudo".to_string())
.chain((!envs.is_empty()).then_some("env".to_string()))
.chain(envs.iter().map(|(key, value)| format!("{key}={value}")))
.chain(std::iter::once(program.to_string()))
.chain(args.iter().cloned())
.collect::<Vec<_>>()
.join(" ");View on GitHub (pinned to 9dcfcaa0dc)
Solutions
- Run `sudo -v` interactively immediately before, or configure NOPASSWD for the elevated helper in sudoers
- Copy the printed argv and run it manually to see the real exit status and stderr
- Check sudoers covers every privileged subcommand mise invokes
- Fix the underlying failure of the elevated command once identified from its output
Defensive patterns
Strategy: try-catch
Validate before calling
// Before a batch of elevated operations, confirm sudo will not block or deny
fn elevation_ready() -> Result<()> {
let status = Command::new("sudo").arg("-n").arg("-v").status()?;
if !status.success() {
bail!("sudo credentials unavailable; run `sudo -v` interactively first");
}
Ok(())
} Try / catch
match sudo::run(&program, &args, &envs) {
Err(err) => {
let msg = err.to_string();
if let Some(argv) = msg.strip_suffix(" failed") {
// argv names the exact elevated command; re-run it manually to inspect the real failure
}
return Err(err);
}
ok => ok,
} Prevention
- Authenticate with `sudo -v` immediately before interactive bootstrap runs
- Configure NOPASSWD (or a precise sudoers whitelist) for the elevated helper in CI/cron
- Never treat this error as transient: inspect the child command's own failure first
When it happens
Trigger: Non-interactive runs using `sudo -n` after the timestamp expired; sudoers rules that deny or do not whitelist the specific command; the privileged bootstrap step failing on a real system error.
Common situations: CI/cron without NOPASSWD configured for mise's elevated helper; hardened sudoers whitelists missing one subcommand; privileged apply failing due to underlying system state (disk, permissions).
Related errors
- {program} failed with {status}
- compose command failed with {status}
- {} {} failed: {}
- refusing firewall default incoming {} from an SSH-derived pr
- `launchctl {}` failed: {}
AI-assisted analysis of jdx/mise@9dcfcaa0dc (2026-08-17).
Data as JSON: /api/errors/ce1958d8c72f5112.
Report an issue: GitHub.