coding-horror/basic-computer-games · error

Error reading line!

Error message

Error reading line!

What it means

This panic is triggered by `.expect("Error reading line!")` on `std::io::stdin().read_line()` inside the trigger-pull input loop of Russian Roulette (line 27). The loop reads `"1"` or `"2"` from the player to decide whether to pull the trigger. The `_` arm handles invalid *content*, but `.expect` crashes on I/O-level failures.

Source

Thrown at 76_Russian_Roulette/rust/src/main.rs:27

    println!("HERE IS A REVOLVER.");

    loop {
        println!("TYPE '1' TO SPIN CHAMBER AND PULL TRIGGER");
        println!("TYPE '2' TO GIVE UP.");
        println!("GO");

        let mut tries = 0;

        loop {
            let mut pull_trigger = true;

            loop {
                println!("?");
                let mut input = String::new();

                std::io::stdin()
                    .read_line(&mut input)
                    .expect("Error reading line!");

                match input.trim() {
                    "1" => break,
                    "2" => {
                        pull_trigger = false;
                        break;
                    }
                    _ => println!("Invalid input."),
                }
            }

            if pull_trigger {
                std::thread::sleep(Duration::from_secs(1));

                match rand::thread_rng().gen_range(0..6) {
                    0 => {
                        println!("\tBANG!!!!!   YOU'RE DEAD!");
                        println!("CONDOLENCES WILL BE SENT TO YOUR RELATIVES.");

View on GitHub (pinned to 5301155192)

Solutions

  1. Replace `.expect` with a `match` that exits gracefully on EOF (`Ok(0)`) and retries or exits on `Err`.
  2. On EOF, break the trigger loop and end the game with a summary message.
  3. Provide piped input that covers all trigger-pull prompts for a full game session.

Example fix

// before
std::io::stdin().read_line(&mut input).expect("Error reading line!");

// after
match std::io::stdin().read_line(&mut input) {
    Ok(0) => { println!("\nGame interrupted."); return; }
    Ok(_) => {}
    Err(e) => { eprintln!("Input error: {}", e); return; }
}
Defensive patterns

Strategy: try-catch

Validate before calling

use std::io::IsTerminal;
if !io::stdin().is_terminal() {
    // Provide input via pipe or file
}

Type guard

fn read_choice() -> Option<String> {
    let mut input = String::new();
    match std::io::stdin().read_line(&mut input) {
        Ok(0) | Err(_) => None,
        Ok(_) => Some(input),
    }
}

Try / catch

match std::io::stdin().read_line(&mut input) {
    Ok(0) => { println!("\nGame interrupted."); return; }
    Ok(_) => { /* match on "1" / "2" / _ */ }
    Err(e) => { eprintln!("{}", e); return; }
}

Prevention

When it happens

Trigger: Stdin returns `Err` or EOF while the player is at the trigger-pull prompt. The input match (`"1" => break`, `"2" => pull_trigger = false; break`, `_ => println!`) only runs after a successful read, so malformed input is retried while stream failure crashes.

Common situations: Non-interactive execution. Piped input file with too few lines. SSH drop. Process launched without a TTY.

Related errors


AI-assisted analysis of coding-horror/basic-computer-games@5301155192 (2026-08-13). Data as JSON: /api/errors/101cc9d07cf38644. Report an issue: GitHub.