coding-horror/basic-computer-games · error
failed to read input
Error message
failed to read input
What it means
A panic via .expect("failed to read input") on io::stdin().read_line() in get_dollar_value_in_cents_from_user() of the Change Rust port, used to read a dollar amount. read_line returns Err only on I/O-level failure (closed stdin, EOF, broken pipe); non-numeric characters are filtered out afterward (the code keeps only digits and the first '.'). The expect thus aborts only when stdin itself cannot be read.
Source
Thrown at 22_Change/rust/src/main.rs:132
}
/**
* get number of money from user input
*/
fn get_dollar_value_in_cents_from_user(prompt:&str) -> i16 {
let mut value:i16;
//input loop
loop {
//data
let mut raw_input = String::new();
//print prompt
print!("{}",prompt);
//flush std out // allows prompt to be on same line as input
stdout().flush().expect("failed to flush");
//get input
io::stdin().read_line(&mut raw_input).expect("failed to read input");
//filter out characters that aren't numbers or '.'
let mut no_prior_periods = true;
raw_input = raw_input.chars().filter(|c| {
if c.eq_ignore_ascii_case(&'.') && no_prior_periods {
no_prior_periods = false;
true
} else {
c.is_ascii_digit()
}
}).collect();
//should only be (at most) 1 .
if !raw_input.contains(".") { raw_input += ".00";} //if there are none, add one
//ensure there are at least 2 trailing digits
if raw_input[raw_input.find('.').unwrap_or(raw_input.len())..].len() <= 2 { //if a slice of the string from the . onwards is less than or equal to 2, add two 0's to the end
raw_input += "00"
}View on GitHub (pinned to 5301155192)
Solutions
- Provide a numeric line for each amount prompt in piped input.
- Run interactively so stdin remains open.
- Swap .expect for a match that returns a default or exits cleanly on read error.
Example fix
// before
io::stdin().read_line(&mut raw_input).expect("failed to read input");
// after
if io::stdin().read_line(&mut raw_input).is_err() {
println!("\nUnable to read input. Exiting.");
std::process::exit(1);
} Defensive patterns
Strategy: try-catch
Validate before calling
// Ensure stdin is open / has lines before prompting; provide a numeric line per amount prompt when piping.
Try / catch
// Replace .expect with a match
match io::stdin().read_line(&mut raw_input) {
Ok(_) => { /* filter digits, parse cents */ }
Err(_) | Ok(0) => { println!("Input unavailable. Exiting."); std::process::exit(1); }
} Prevention
- Match read_line's Result; don't .expect on user input.
- Provide a numeric line per amount prompt in piped runs.
- Exit cleanly on EOF (Ok(0)).
When it happens
Trigger: stdin closed or exhausted before the amount prompt is answered; redirected input that ends; broken pipe to stdin; `< /dev/null`.
Common situations: Piped input fixtures with too few lines; headless/CI runs with no TTY; a feeder script closing stdin after a fixed count.
Related errors
AI-assisted analysis of coding-horror/basic-computer-games@5301155192 (2026-08-13).
Data as JSON: /api/errors/94946ae0598a79a9.
Report an issue: GitHub.