atuinsh/atuin · error
Failed to read from input
Error message
Failed to read from input
What it means
read_user_password() backs interactive login: when `atuin login` runs without --password, it calls rpassword::prompt_password to read the account password hidden from the terminal. A failed read — no TTY, closed or empty stdin, I/O error — makes the expect panic with 'Failed to read from input'. Other flows reuse it (account delete at delete.rs:28, register).
Source
Thrown at crates/atuin/src/command/client/account/login.rs:352
let _ = meta.delete_hub_session().await;
}
crate::print_error::print_error(
"Wrong encryption key",
"The encryption key on this machine does not match the data on the server. \
You have been logged out.\n\n\
To fix this, find your existing key by running `atuin key` on a machine that \
already syncs successfully, then run `atuin login` again here with that key.",
);
std::process::exit(1);
}
pub(super) fn or_user_input(value: Option<String>, name: &'static str) -> String {
value.unwrap_or_else(|| read_user_input(name).unwrap_or_default())
}
pub(super) fn read_user_password() -> String {
let password = prompt_password("Please enter password: ");
password.expect("Failed to read from input")
}
/// Returns `None` if stdin reached end of input before a line was read.
fn read_user_input(name: &'static str) -> Option<String> {
eprint!("Please enter {name}: ");
get_input().expect("Failed to read from input")
}
#[cfg(test)]
mod tests {
use atuin_common::encryption::paseto_v4;
use rstest::rstest;
#[rstest]
fn mnemonic_round_trip() {
let key = paseto_v4::Key::from([
3, 1, 4, 1, 5, 9, 2, 6, 5, 3, 5, 8, 9, 7, 9, 3, 2, 3, 8, 4, 6, 2, 6, 4, 3, 3, 8, 3, 2,
7, 9, 5,View on GitHub (pinned to 202f6ad98e)
Solutions
- Provide the credentials via flags: atuin login --username "$U" --password "$P" --key "$K"
- Allocate a TTY when prompting must run (docker run -it, pty wrappers)
- When driving prompts from a pipe, send newline-terminated lines for every prompt (password, key) and keep stdin open
Example fix
# before — panics when stdin has no TTY atuin login -u alice # after atuin login -u alice -p "$ATUIN_PASSWORD" -k "$ATUIN_KEY"
Defensive patterns
Strategy: validation
Validate before calling
use std::io::IsTerminal;
if std::env::args().any(|a| a == "login")
&& !std::env::args().any(|a| a.starts_with("--password") || a == "-p")
&& !std::io::stdin().is_terminal()
{
eprintln!("atuin login needs --password when stdin is not a TTY");
std::process::exit(2);
} Try / catch
let password = match rpassword::prompt_password("Please enter password: ") {
Ok(pw) => pw,
Err(e) => {
eprintln!("cannot read password (stdin/TTY unavailable): {e}; pass --password");
std::process::exit(2);
}
}; Prevention
- Provide --username/--password/--key flags for every headless login
- Allocate a TTY for interactive first-run login flows
- Remember delete/register flows prompt the same way; pass their flags too
When it happens
Trigger: Running `atuin login` (or register/delete) without -p/--password where no interactive terminal exists: piped or closed stdin, cron, CI, docker without -t.
Common situations: Headless machine setup with `atuin login -u name` but no -p; automation assuming env-based login; containers without an allocated TTY.
Related errors
- Failed to read from input
- failed to create client
- Failed to compute stats
- bug in list query. please report
- bug in search query. please report
AI-assisted analysis of atuinsh/atuin@202f6ad98e (2026-08-16).
Data as JSON: /api/errors/5ca40bc5d1e02b6c.
Report an issue: GitHub.