jdx/mise · error · eyre::Report

sudo requires a password but no TTY is available. Run manual

Error message

sudo requires a password but no TTY is available. Run manually:
  {manual_cmd}

What it means

When stderr is not an attended TTY, mise probes sudo non-interactively by running `sudo -n true` with all stdio nulled; if that probe fails, sudo would need to prompt for a password but cannot, so ensure_elevation_available aborts with the manual command. This guards non-interactive contexts (CI, cron, piped output) from hanging on a password prompt that can never be answered.

Source

Thrown at src/system/sudo.rs:276

        );
    }
    if crate::file::which("sudo").is_none() {
        bail!(
            "sudo not found. Run as root:\n  {}",
            manual_cmd.trim_start_matches("sudo ")
        );
    }
    if !console::user_attended_stderr() {
        let ok = Command::new("sudo")
            .args(["-n", "true"])
            .stdin(Stdio::null())
            .stdout(Stdio::null())
            .stderr(Stdio::null())
            .status()
            .map(|status| status.success())
            .unwrap_or(false);
        if !ok {
            bail!(
                "sudo requires a password but no TTY is available. Run manually:\n  {manual_cmd}"
            );
        }
    }
    Ok(())
}

View on GitHub (pinned to 9dcfcaa0dc)

Solutions

  1. Run the manual command from the error message interactively once, then retry the mise operation while credentials are cached
  2. Configure passwordless sudo for the specific helpers mise runs: `youruser ALL=(root) NOPASSWD: /usr/bin/apt-get` in /etc/sudoers.d/
  3. Run mise as root in environments (containers/CI) where an interactive password is impossible

Example fix

# /etc/sudoers.d/mise (after)
runner ALL=(root) NOPASSWD: /usr/bin/apt-get, /usr/bin/systemctl
Defensive patterns

Strategy: validation

Validate before calling

use std::process::{Command, Stdio};
fn sudo_noninteractive_ok() -> bool {
    // same probe mise uses: `sudo -n true` with stdio silenced
    Command::new("sudo").args(["-n", "true"])
        .stdin(Stdio::null()).stdout(Stdio::null()).stderr(Stdio::null())
        .status().map(|s| s.success()).unwrap_or(false)
}

Prevention

When it happens

Trigger: console::user_attended_stderr() is false AND `sudo -n true` fails - i.e. no cached sudo credentials and no NOPASSWD rule, in a pipeline, CI job, or ssh -T session.

Common situations: CI jobs that assume inherited sudo credentials; cron-invoked mise bootstrap; scripts run with stderr redirected; fresh sessions where the sudo timestamp is expired.

Related errors


AI-assisted analysis of jdx/mise@9dcfcaa0dc (2026-08-17). Data as JSON: /api/errors/6e66b78cd1603500. Report an issue: GitHub.