coding-horror/basic-computer-games · error
Failed to read the line
Error message
Failed to read the line
What it means
In 54_Letter, inside a loop of up to 999999 guesses, the game reads the player's letter guess via io::stdin().read_line(&mut guess).expect("Failed to read the line"). The guess is trimmed, uppercased, and compared to a random character A-Z. There is no parse step, so the .expect() is the only failure point — an empty or wrong letter is handled by the Ordering comparison, but a stdin I/O failure panics.
Source
Thrown at 54_Letter/rust/src/main.rs:26
"LETTER", "CREATIVE COMPUTING MORRISTOWN, NEW JERSEY"
);
println!("LETTER GUESSING GAME\n");
println!("I'LL THINK OF A LETTER OF THE ALPHABET, A TO Z.");
println!("TRY TO GUESS MY LETTER AND I'LL GIVE YOU CLUES");
println!("AS TO HOW CLOSE YOU'RE GETTING TO MY LETTER.");
loop {
let gen_character = rand::thread_rng().gen_range('A'..='Z'); // generates a random character between A and Z
let gen_character = String::from(gen_character);
println!("\nO.K., I HAVE A LETTER. START GUESSING.");
for i in 0..999999 {
println!("\nWHAT IS YOUR GUESS?");
let mut guess = String::new();
io::stdin()
.read_line(&mut guess)
.expect("Failed to read the line");
println!("{}", gen_character);
let guess = guess.trim().to_ascii_uppercase();
match guess.cmp(&gen_character) {
Ordering::Less => println!("\nTOO LOW. TRY A HIGHER LETTER."),
Ordering::Greater => println!("\nTOO HIGH. TRY A LOWER LETTER."),
Ordering::Equal => {
println!("\nYOU GOT IT IN {} GUESSES!!", i + 1);
if i >= 4 {
println!("BUT IT SHOULDN'T TAKE MORE THAN 5 GUESSES!\n");
} else {
println!("{}", std::iter::repeat("💖").take(15).collect::<String>());
println!("GOOD JOB !!!!!");
}
break;
}
}
}
println!("\nLET'S PLAY AGAIN.....");View on GitHub (pinned to 5301155192)
Solutions
- Replace .expect() with .unwrap_or_default() so I/O failure yields an empty string, which the Ordering comparison handles as a wrong guess
- Use match to detect Ok(0) (EOF) and break the guess loop
- Return early from the game on Err
Example fix
// before
let mut guess = String::new();
io::stdin()
.read_line(&mut guess)
.expect("Failed to read the line");
println!("{}", gen_character);
// after
let mut guess = String::new();
let _ = io::stdin().read_line(&mut guess);
println!("{}", gen_character); Defensive patterns
Strategy: fallback
Try / catch
let mut guess = String::new(); let _ = io::stdin().read_line(&mut guess); // empty string compares as Ordering::Less or Greater, // which the existing match handles by re-prompting
Prevention
- For guess loops with no parse step, let I/O failures produce empty strings that the comparison logic handles as wrong guesses
- Use let _ = read_line(...) when the downstream logic is a comparison that naturally handles unexpected values
- Test letter-guessing games with truncated input to verify the Ordering comparison path handles empty strings without panicking
When it happens
Trigger: The game prompts 'WHAT IS YOUR GUESS?' and stdin returns Err or EOF. Invalid guesses (empty string, multiple characters) are handled by the comparison logic (they'll be Ordering::Less or Greater), but missing input is not.
Common situations: Piped input that runs out before the letter is guessed, pressing Ctrl+D at a guess prompt, or CI tests that provide insufficient guesses.
Related errors
- Failed to read the line
- Error reading from stdin
- Error reading line.
- ~~Failed reading line!~~
- Failed to get Input
AI-assisted analysis of coding-horror/basic-computer-games@5301155192 (2026-08-13).
Data as JSON: /api/errors/7f9ef1428effed1a.
Report an issue: GitHub.