coding-horror/basic-computer-games · error

input error

Error message

input error

What it means

In 53_King, main calls intro(&mut input, &mut rng).expect("input error") where intro returns io::Result<State>. Unlike the other errors, this .expect() wraps an entire function, not a single read_line. The panic can originate from any I/O failure inside intro: stdout().flush()?, input.read_line()?, or any read_int/read_and_verify_int call that propagates an error via ?. The single message 'input error' obscures which specific I/O operation failed.

Source

Thrown at 53_King/rust/src/main.rs:13

#![forbid(unsafe_code)]

use fastrand::Rng;
use std::io;
use std::io::{stdin, stdout, BufRead, Write};

// global variable `N5` in the original game
const TERM_LENGTH: u32 = 8;

fn main() {
    let mut rng = Rng::new();
    let mut input = stdin().lock();
    let mut state = intro(&mut input, &mut rng).expect("input error");

    loop {
        let land_price = 95 + rng.u32(0..10);
        let plant_price = 10 + rng.u32(0..5);
        print_state(&state, land_price, plant_price);
        state = match next_round(&mut input, &mut rng, &state, land_price, plant_price)
            .expect("input error")
        {
            RoundEnd::Next(s) => s,
            RoundEnd::GameOver(msg) => {
                println!("{}", msg);
                return;
            }
        }
    }
}

// The game is round based (one round per in-game year).

View on GitHub (pinned to 5301155192)

Solutions

  1. Replace .expect() with match to print a user-friendly message on Err before exiting
  2. Use if let Err(e) = intro(...) to log the actual io::Error for debugging, since the generic 'input error' message hides the root cause
  3. Wrap the main function body in a helper that returns Result<(), Box<dyn Error>> and use ? throughout, then print the error in main

Example fix

// before
let mut state = intro(&mut input, &mut rng).expect("input error");

// after
let mut state = match intro(&mut input, &mut rng) {
    Ok(s) => s,
    Err(e) => {
        eprintln!("Failed to read input during intro: {}", e);
        return;
    }
};
Defensive patterns

Strategy: try-catch

Try / catch

let mut state = match intro(&mut input, &mut rng) {
    Ok(s) => s,
    Err(e) => {
        eprintln!("Input error during intro: {}", e);
        return;
    }
};

Prevention

When it happens

Trigger: Any I/O failure during the intro sequence: flushing the 'DO YOU WANT INSTRUCTIONS?' prompt fails (broken pipe), reading the instruction/again/custom-state choice hits EOF, or reading numeric state values (money, countrymen, workers, land) fails because stdin is exhausted.

Common situations: Piped input that ends during the intro sequence, pressing Ctrl+D while answering intro questions, or CI tests that don't cover the 'again' (resume savegame) branch which requires many more input lines.

Related errors


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