{"record":{"id":"6e66b78cd1603500","repo":"jdx/mise","slug":"sudo-requires-a-password-but-no-tty-is-available","errorCode":null,"errorMessage":"sudo requires a password but no TTY is available. Run manually:\n  {manual_cmd}","messagePattern":"sudo requires a password but no TTY is available\\. Run manually:\n  (.+?)","errorType":"exception","errorClass":"eyre::Report","httpStatus":null,"severity":"error","filePath":"src/system/sudo.rs","lineNumber":276,"sourceCode":"        );\n    }\n    if crate::file::which(\"sudo\").is_none() {\n        bail!(\n            \"sudo not found. Run as root:\\n  {}\",\n            manual_cmd.trim_start_matches(\"sudo \")\n        );\n    }\n    if !console::user_attended_stderr() {\n        let ok = Command::new(\"sudo\")\n            .args([\"-n\", \"true\"])\n            .stdin(Stdio::null())\n            .stdout(Stdio::null())\n            .stderr(Stdio::null())\n            .status()\n            .map(|status| status.success())\n            .unwrap_or(false);\n        if !ok {\n            bail!(\n                \"sudo requires a password but no TTY is available. Run manually:\\n  {manual_cmd}\"\n            );\n        }\n    }\n    Ok(())\n}\n","sourceCodeStart":258,"sourceCodeEnd":283,"githubUrl":"https://github.com/jdx/mise/blob/9dcfcaa0dc8747a2577d3270b69bb9d8313b2807/src/system/sudo.rs#L258-L283","documentation":"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.","triggerScenarios":"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.","commonSituations":"CI jobs that assume inherited sudo credentials; cron-invoked mise bootstrap; scripts run with stderr redirected; fresh sessions where the sudo timestamp is expired.","solutions":["Run the manual command from the error message interactively once, then retry the mise operation while credentials are cached","Configure passwordless sudo for the specific helpers mise runs: `youruser ALL=(root) NOPASSWD: /usr/bin/apt-get` in /etc/sudoers.d/","Run mise as root in environments (containers/CI) where an interactive password is impossible"],"exampleFix":"# /etc/sudoers.d/mise (after)\nrunner ALL=(root) NOPASSWD: /usr/bin/apt-get, /usr/bin/systemctl","handlingStrategy":"validation","validationCode":"use std::process::{Command, Stdio};\nfn sudo_noninteractive_ok() -> bool {\n    // same probe mise uses: `sudo -n true` with stdio silenced\n    Command::new(\"sudo\").args([\"-n\", \"true\"])\n        .stdin(Stdio::null()).stdout(Stdio::null()).stderr(Stdio::null())\n        .status().map(|s| s.success()).unwrap_or(false)\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Configure NOPASSWD sudoers entries for the specific helpers in CI/cron environments","Run `sudo -v` in an attended shell right before non-attended runs to seed the timestamp","Never pipe stderr away in scripts that need sudo - an attended TTY lets sudo prompt instead of failing"],"tags":["sudo","tty","non-interactive","ci","authentication"],"backgroundTag":"sudo-no-tty","analyzedSha":"9dcfcaa0dc8747a2577d3270b69bb9d8313b2807","analyzedAt":"2026-08-17T14:28:50.624Z","schemaVersion":2},"datasetVersion":"2026-08-21T18:17:14.833Z"}