coding-horror/basic-computer-games · error
Failed read_line
Error message
Failed read_line
What it means
In 43_Hammurabi, get_input reads a line and parses it as u32, returning Option<u32> — Some on successful parse, None on parse failure. However, the read_line call itself uses .expect("Failed read_line"), so an I/O failure (EOF, broken pipe) panics before the graceful parse-failure path can execute. This creates an asymmetry: non-numeric input returns None (handled), but missing input crashes.
Source
Thrown at 43_Hammurabi/rust/src/main.rs:218
println!("YOUR PERFORMANCE COULD HAVE BEEN SOMEWHAT BETTER, BUT");
println!("REALLY WASN'T TOO BAD AT ALL. {haters} PEOPLE");
println!("WOULD DEARLY LIKE TO SEE YOU ASSASSINATED BUT WE ALL HAVE OUR");
println!("TRIVIAL PROBLEMS.");
} else {
println!("A FANTASTIC PERFORMANCE!!! CHARLEMANGE, DISRAELI, AND");
println!("JEFFERSON COMBINED COULD NOT HAVE DONE BETTER!\n");
}
for _ in 1..10 {
println!();
}
}
println!("\nSO LONG FOR NOW.\n");
}
fn get_input() -> Option<u32> {
let mut input = String::new();
io::stdin().read_line(&mut input).expect("Failed read_line");
match input.trim().parse() {
Ok(num) => Some(num),
Err(_) => None,
}
}
fn gen_random() -> u32 {
let r: f32 = rand::thread_rng().gen();
(r * 5.0 + 1.0) as u32
}
fn impossible_task() {
println!("HAMURABI: I CANNOT DO WHAT YOU WISH.");
println!("GET YOURSELF ANOTHER STEWARD!!!!!");
}
fn insufficient_grain(grain: u32) {
println!("HAMURABI: THINK AGAIN. YOU HAVE ONLY");View on GitHub (pinned to 5301155192)
Solutions
- Replace .expect() with .unwrap_or_default() — an empty string fails to parse as u32, so get_input returns None, which callers already handle
- Use match on read_line to return None on Ok(0) (EOF) or Err
- Change the function to return Result<Option<u32>, io::Error> to separate I/O errors from parse failures
Example fix
// before
fn get_input() -> Option<u32> {
let mut input = String::new();
io::stdin().read_line(&mut input).expect("Failed read_line");
match input.trim().parse() {
Ok(num) => Some(num),
Err(_) => None,
}
}
// after
fn get_input() -> Option<u32> {
let mut input = String::new();
if io::stdin().read_line(&mut input).unwrap_or(0) == 0 {
return None;
}
input.trim().parse().ok()
} Defensive patterns
Strategy: fallback
Try / catch
fn get_input() -> Option<u32> {
let mut input = String::new();
if io::stdin().read_line(&mut input).unwrap_or(0) == 0 {
return None;
}
input.trim().parse().ok()
} Prevention
- When a function returns Option to represent parse failures, I/O failures should also return None — not panic — so callers handle them uniformly
- Use unwrap_or(0) on read_line to collapse I/O errors into an EOF signal, which then fails to parse and returns None
- Ensure symmetric error handling: if non-numeric input returns None, missing input should too
When it happens
Trigger: The Hammurabi game prompts for a numeric input (bushels to distribute, land to buy, etc.) and stdin is at EOF or the read fails. Non-numeric text like 'abc' correctly returns None, but EOF does not.
Common situations: Piped input that exhausts mid-game (Hammurabi has many sequential prompts per round), pressing Ctrl+D during a steward decision, or CI tests that don't supply all required inputs.
Related errors
- Error reading from stdin
- Error reading line.
- ~~Failed reading line!~~
- Failed to get Input
- Failed to read line
AI-assisted analysis of coding-horror/basic-computer-games@5301155192 (2026-08-13).
Data as JSON: /api/errors/99acdfefa5001d65.
Report an issue: GitHub.