coding-horror/basic-computer-games · error

CANNOT READ INPUT!

Error message

CANNOT READ INPUT!

What it means

A panic via .expect("CANNOT READ INPUT!") on io::stdin().read_line() inside get_number_from_user_input() of the Blackjack Rust port, used to read numeric bets/choices within a min..max range. read_line returns Err only on I/O-level failure (closed stdin, EOF, broken pipe); out-of-range or non-numeric input is handled by the parse branch with a re-prompt. The expect aborts on any read error.

Source

Thrown at 10_Blackjack/rust/src/main.rs:573

    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 number
        match raw_input.trim().parse::<usize>() {
            Ok(i) => {
                if i < min || i > max { //input out of desired range
                    println!("INPUT OUT OF VALID RANGE.  TRY AGAIN.  {}-{}",min,max);
                    continue; // run the loop again
                }
                else {
                    break i;// this escapes the loop, returning i
                }
            },
            Err(e) => {
                println!("INVALID INPUT.  TRY AGAIN.  {}", e.to_string().to_uppercase());
                continue; // run the loop again
            }
        };
    };

View on GitHub (pinned to 5301155192)

Solutions

  1. Provide a numeric line within the valid range for every prompt in piped input.
  2. Run interactively so stdin remains open.
  3. Swap .expect for `match` that exits or returns a default on read error.

Example fix

// before
io::stdin().read_line(&mut raw_input).expect("CANNOT READ INPUT!");

// after
if io::stdin().read_line(&mut raw_input).is_err() {
    println!("\nInput unavailable. Exiting.");
    std::process::exit(1);
}
Defensive patterns

Strategy: try-catch

Validate before calling

// Ensure stdin is open before prompting; provide one in-range numeric line per call when piping.

Try / catch

// Replace .expect with a match
match io::stdin().read_line(&mut raw_input) {
    Ok(_) => { /* parse usize in [min,max] */ }
    Err(_) | Ok(0) => { println!("Input closed. Exiting."); std::process::exit(1); }
}

Prevention

When it happens

Trigger: stdin closed or exhausted before a numeric prompt is answered; redirected input that ends mid-game; broken pipe to stdin.

Common situations: Test/CI runs whose input fixture runs out of lines; piping /dev/null; a feeder script that closes stdin after a fixed count.

Related errors


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