coding-horror/basic-computer-games · error

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 read_input_integer() of the Batnum Rust port, used to read the count of objects in a Nim-like game. read_line returns Err only on I/O failure (closed/exhausted stdin, broken pipe); invalid numeric text is handled separately by the parse branch which re-prompts. The expect converts any read error into a panic.

Source

Thrown at 08_Batnum/rust/src/main.rs:134

    fn get_min_max() -> (usize, usize) {
        print!("ENTER MIN ");
        let _ = io::stdout().flush();
        let min = read_input_integer();

        print!("ENTER MAX ");
        let _ = io::stdout().flush();
        let max = read_input_integer();

        (min, max)
    }
}

fn read_input_integer() -> usize {
    loop {
        let mut input = String::new();
        io::stdin()
            .read_line(&mut input)
            .expect("Failed to read line");
        match input.trim().parse::<usize>() {
            Ok(num) => {
                if num == 0 {
                    print!("Must be greater than zero ");
                    let _ = io::stdout().flush();
                    continue;
                }
                return num;
            }
            Err(_err) => {
                print!("Please enter a number greater than zero ");
                let _ = io::stdout().flush();
                continue;
            }
        }
    }
}

View on GitHub (pinned to 5301155192)

Solutions

  1. Ensure the piped input contains a numeric line for each call to read_input_integer.
  2. Run interactively so stdin stays open.
  3. Swap .expect for `match`/`?` that returns a default or exits on read error.

Example fix

// before
io::stdin().read_line(&mut input).expect("Failed to read line");

// after
if io::stdin().read_line(&mut input).is_err() {
    eprintln!("Input stream closed.");
    std::process::exit(1);
}
Defensive patterns

Strategy: try-catch

Validate before calling

// Detect that stdin is exhausted before relying on read_line
use std::io::IsTerminal;
if !std::io::stdin().is_terminal() {
    // ensure the input fixture still has lines
}

Try / catch

// Replace .expect with a match that exits cleanly
match io::stdin().read_line(&mut input) {
    Ok(0) | Err(_) => { eprintln!("Input closed."); std::process::exit(1); }
    Ok(_) => { /* parse num */ }
}

Prevention

When it happens

Trigger: stdin reaches EOF before a number is entered; stdin is closed or redirected from a stream that ends early; a broken pipe between the feeder and the process.

Common situations: Piping a fixture with too few lines; running under `< /dev/null`; CI harness that closes stdin once output stops.

Related errors


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