coding-horror/basic-computer-games · error
Failed to read line
Error message
Failed to read line
What it means
In 35_Even_Wins, human_play reads how many marbles the human wants to take via io::stdin().read_line(&mut num).expect("Failed to read line"). The input is parsed as u32 inside a match that already handles parse failures by printing an error and continuing the loop. The .expect() guards only the I/O layer: a stdin EOF or read failure panics, while invalid numbers are handled gracefully.
Source
Thrown at 35_Even_Wins/rust/src/main.rs:107
println!("You are the winner! Congratulations!");
} else {
println!("The computer wins: all hail mighty silicon!");
}
println!("");
}
}
fn human_play(game: &mut Game) {
println!("It's your turn!");
loop {
let max_take = game.get_max_take();
println!("Marbles to take? ({} - {}) --> ", game.min_take, max_take);
let mut num = String::new();
io::stdin()
.read_line(&mut num)
.expect("Failed to read line");
let _: u32 = match num.trim().to_uppercase().parse() {
Ok(num) => {
if game.take(num) {
println!("Okay, taking {} marble ...", num);
break;
};
println!("");
continue;
}
_ => {
println!("Please enter a whole number from 1 to 4");
println!("");
continue;
}
};
}
}View on GitHub (pinned to 5301155192)
Solutions
- Replace .expect() with .unwrap_or_default() — an empty string will fail the u32 parse, triggering the existing 'Please enter a whole number' retry
- Use match on read_line's Result to break out of the loop and end the game on EOF
- Return early from human_play on I/O error, signaling the game to end
Example fix
// before
let mut num = String::new();
io::stdin()
.read_line(&mut num)
.expect("Failed to read line");
let _: u32 = match num.trim().to_uppercase().parse() {
// after
let mut num = String::new();
let _ = io::stdin().read_line(&mut num);
let _: u32 = match num.trim().to_uppercase().parse() { Defensive patterns
Strategy: fallback
Try / catch
let mut num = String::new(); let _ = io::stdin().read_line(&mut num); // empty string from I/O failure falls through to parse error, // which the existing match handles by re-prompting
Prevention
- When a parse-failure retry loop already exists, use let _ = read_line(...) so I/O failures degrade to parse failures and reuse the same retry path
- Use unwrap_or_default() or let _ = to avoid panicking on reads that feed into existing validation loops
- Ensure game-loop input reads are resilient to EOF by letting downstream validation catch empty strings
When it happens
Trigger: The human player's turn arrives and stdin is at EOF (piped input exhausted, Ctrl+D pressed), or the read syscall fails. The game loop would handle a bad number, but cannot recover from a missing input.
Common situations: Automated testing of the Even_Wins game where the input script runs out during a human turn, or a user closing the terminal when prompted for a marble count.
Related errors
- Error reading from stdin
- Error reading line.
- ~~Failed reading line!~~
- Failed to get Input
- Your input is not correct
AI-assisted analysis of coding-horror/basic-computer-games@5301155192 (2026-08-13).
Data as JSON: /api/errors/8469531ec51a871e.
Report an issue: GitHub.