coding-horror/basic-computer-games · warning
Failed to read line
Error message
Failed to read line
What it means
A panic via .expect("Failed to read line") on io::stdin().read_line() in Blackjack's rules-display function that prints instructions then waits for ENTER to continue. read_line fails only on I/O-level errors (closed stdin, EOF, broken pipe). Because the read result is discarded into a fresh String, any read failure aborts the process at the 'PRESS ENTER TO CONTINUE' pause.
Source
Thrown at 10_Blackjack/rust/src/main.rs:557
THIS IS THE GAME OF 21. AS MANY AS 7 PLAYERS MAY PLAY THE
GAME. ON EACH DEAL, BETS WILL BE ASKED FOR, AND THE
PLAYERS' BETS SHOULD BE TYPED IN. THE CARDS WILL THEN BE
DEALT, AND EACH PLAYER IN TURN PLAYS HIS HAND. THE
FIRST RESPONSE SHOULD BE EITHER 'D', INDICATING THAT THE
PLAYER IS DOUBLING DOWN, 'S', INDICATING THAT HE IS
STANDING, 'H', INDICATING HE WANTS ANOTHER CARD, OR '/',
INDICATING THAT HE WANTS TO SPLIT HIS CARDS. AFTER THE
INITIAL RESPONSE, ALL FURTHER RESPONSES SHOULD BE 'S' OR
'H', UNLESS THE CARDS WERE SPLIT, IN WHICH CASE DOUBLING
DOWN IS AGAIN PERMITTED. IN ORDER TO COLLECT FOR
BLACKJACK, THE INITIAL RESPONSE SHOULD BE 'S'.
NUMBER OF PLAYERS
NOTE:'/' (splitting) is not currently implemented, and does nothing
PRESS ENTER TO CONTINUE
");
io::stdin().read_line(&mut String::new()).expect("Failed to read line");
}
/**
* gets a usize integer from user input
*/
fn get_number_from_user_input(prompt: &str, min:usize, max:usize) -> usize {
//input loop
return loop {
let mut raw_input = String::new(); // temporary variable for user input that can be parsed later
//print prompt
println!("{}", prompt);
stdout().flush().expect("Failed to flush to stdout.");
//read user input from standard input, and store it to raw_input
//raw_input.clear(); //clear input
io::stdin().read_line(&mut raw_input).expect( "CANNOT READ INPUT!");
//from input, try to read a numberView on GitHub (pinned to 5301155192)
Solutions
- Include a trailing newline (ENTER) in piped input for the rules pause.
- Run interactively.
- Replace .expect with `let _ = io::stdin().read_line(&mut String::new());` to ignore failure at the continue prompt.
Example fix
// before
io::stdin().read_line(&mut String::new()).expect("Failed to read line");
// after
let _ = io::stdin().read_line(&mut String::new()); Defensive patterns
Strategy: fallback
Validate before calling
// The read result is irrelevant; just ignore it so EOF won't abort.
Try / catch
// Discard the read result for the continue prompt let _ = io::stdin().read_line(&mut String::new());
Prevention
- Never .expect a read whose value you discard (continue/exit prompts).
- Include a trailing newline in piped input if the pause must return.
- Gate the pause behind is_terminal() for non-interactive use.
When it happens
Trigger: The program prints the rules and waits for ENTER, but stdin is closed or at EOF (piped input exhausted, /dev/null, broken pipe); a non-interactive run that never supplies the ENTER.
Common situations: Piping pre-recorded input that omits the final ENTER; running headless with no TTY; CI that closes stdin after dealing setup lines.
Related errors
AI-assisted analysis of coding-horror/basic-computer-games@5301155192 (2026-08-13).
Data as JSON: /api/errors/6ead1dcbcdca289a.
Report an issue: GitHub.