coding-horror/basic-computer-games · error
Failed to read the line
Error message
Failed to read the line
What it means
Inside the ask_question function for the Synonym game, read_line().expect("Failed to read the line") reads the player's answer inside an infinite loop. The panic fires only on io::Error from read_line, not on EOF. On EOF (Ok(0)) the trimmed answer is empty, which is neither 'HELP' nor a match in this_question, so the loop repeats indefinitely — printing the prompt and reading EOF forever in a busy-spin.
Source
Thrown at 85_Synonym/rust/src/main.rs:35
println!("LANGUAGE WHICH HAS THE SAME OR VERY NEARLY THE SAME MEANING.");
println!("I CHOOSE A WORD -- YOU TYPE A SYNONYM.");
println!("IF YOU CAN'T THINK OF A SYNONYM, TYPE THE WORD 'HELP'");
println!("AND I WILL TELL YOU A SYNONYM.\n");
}
fn ask_question(mut this_question: Vec<&str>) {
let right_words = ["RIGHT", "CORRECT", "FINE", "GOOD!", "CHECK"];
// use the first one in the main question
let base_word = this_question.remove(0);
loop {
print!(" WHAT IS A SYNONYM OF {base_word}? ");
io::stdout().flush().unwrap();
let mut answer: String = String::new();
io::stdin()
.read_line(&mut answer)
.expect("Failed to read the line");
let answer = answer.trim();
if answer == "HELP" {
// remove one random from the answers and show it
let random_index = thread_rng().gen_range(0..this_question.len());
println!(
"**** A SYNONYM OF {base_word} IS {}.",
this_question.remove(random_index)
);
} else if this_question.contains(&answer) {
println!("{}", right_words.choose(&mut rand::thread_rng()).unwrap());
break;
}
}
}
fn main() {
const PAGE_WIDTH: usize = 64;
View on GitHub (pinned to 5301155192)
Solutions
- Match on read_line's Result; on Ok(0) break the loop or call process::exit(0) since the user has disconnected.
- On Err(e), print the error and break the outer quiz loop gracefully.
- Add a maximum-retry or abandon-on-EOF flag so the quiz terminates cleanly when input is exhausted.
- For testing, pipe enough synonym answers to satisfy every question in the quiz.
Example fix
// before
io::stdin()
.read_line(&mut answer)
.expect("Failed to read the line");
// after
match io::stdin().read_line(&mut answer) {
Ok(0) => { println!("\nGoodbye!"); return; }
Ok(_) => {}
Err(e) => { eprintln!("Input error: {e}"); return; }
} Defensive patterns
Strategy: try-catch
Validate before calling
// Break the quiz loop on EOF or error instead of spinning forever
match io::stdin().read_line(&mut answer) {
Ok(0) => { println!("Goodbye!"); return; }
Err(e) => { eprintln!("Input error: {e}"); return; }
Ok(_) => { /* safe to trim and check answer */ }
} Try / catch
// Inside the loop{...} of ask_question
match io::stdin().read_line(&mut answer) {
Ok(n) if n > 0 => { /* have input, proceed with trim/check */ }
Ok(0) => break, // EOF: exit quiz loop
Err(e) => {
eprintln!("{e}");
break;
}
} Prevention
- Always break infinite input loops on Ok(0) — sticky EOF causes busy-spins otherwise.
- Test quiz programs with truncated piped input to verify they exit rather than hang.
- Use return instead of break if the loop is inside a function with no cleanup needed.
- Flush stdout before read_line (already done here) to ensure prompts appear in non-interactive mode.
When it happens
Trigger: Piped input that runs out while the quiz loop is active. A dropped SSH or terminal session mid-quiz. A broken stdin pipe from a parent process that terminated early.
Common situations: Automated quiz testing with limited piped input. Running the synonym quiz under a script or CI pipeline. Terminal connection lost during interactive play.
Related errors
AI-assisted analysis of coding-horror/basic-computer-games@5301155192 (2026-08-13).
Data as JSON: /api/errors/aa3ecc76bcb24a6d.
Report an issue: GitHub.