coding-horror/basic-computer-games · error
Failed to get input
Error message
Failed to get input
What it means
This panic is triggered by `.expect("Failed to get input")` on `io::stdin().read_line()` at the very start of Stars' `main()` (line 18), when asking whether the player wants instructions. The `.expect` fires on any I/O-level stdin failure. Note that line 20 (`need_instrut[..1]`) would separately panic on empty input with an index-out-of-bounds, but that is a different error from this `read_line` panic.
Source
Thrown at 82_Stars/rust/src/main.rs:18
use rand::Rng;
use std::io;
fn main() {
println!(
"{: >39}\n{: >57}\n\n\n",
"STARS", "CREATIVE COMPUTING MORRISTOWN, NEW JERSEY"
);
// STARS - PEOPLE'S COMPUTER CENTER, MENLO PARK, CA
// A IS LIMIT ON NUMBER, M IS NUMBER OF GUESSES
let a: u32 = 101;
let m: u32 = 7;
let mut need_instrut = String::new();
println!("DO YOU WANT INSTRUCTIONS?");
io::stdin()
.read_line(&mut need_instrut)
.expect("Failed to get input");
if need_instrut[..1].to_ascii_lowercase().eq("y") {
println!("I AM THINKING OF A WHOLE NUMBER FROM 1 TO {}", a - 1);
println!("TRY TO GUESS MY NUMBER. AFTER YOU GUESS, I");
println!("WILL TYPE ONE OR MORE STARS (*). THE MORE");
println!("STARS I TYPE, THE CLOSER YOU ARE TO MY NUMBER.");
println!("ONE STAR (*) MEANS FAR AWAY, SEVEN STARS (*******)");
println!("MEANS REALLY CLOSE! YOU GET {} GUESSES.\n\n", m);
}
loop {
println!("\nOK, I AM THINKING OF A NUMBER, START GUESSING.\n");
let rand_number: i32 = rand::thread_rng().gen_range(1..a) as i32; // generates a random number between 1 and 100
// GUESSING BEGINS, HUMAN GETS M GUESSES
for i in 0..m {
let mut guess = String::new();
println!("YOUR GUESS?");View on GitHub (pinned to 5301155192)
Solutions
- Replace `.expect` with a `match` that handles EOF gracefully and defaults to skipping instructions.
- Guard the `need_instrut[..1]` indexing on line 20 with a length check to prevent the related index-out-of-bounds panic.
- For non-interactive use, pipe `"n\n"` or `"y\n"` as the first line of input.
Example fix
// before
io::stdin()
.read_line(&mut need_instrut)
.expect("Failed to get input");
// after
match io::stdin().read_line(&mut need_instrut) {
Ok(0) => { println!("No input detected. Starting game without instructions."); }
Ok(_) => {}
Err(e) => { eprintln!("Input error: {}", e); return; }
}
// also fix the indexing:
// before: if need_instrut[..1].to_ascii_lowercase().eq("y")
// after: if need_instrut.trim_start().starts_with('y') Defensive patterns
Strategy: validation
Validate before calling
// Pre-check stdin and guard against empty input
use std::io::IsTerminal;
if !io::stdin().is_terminal() {
eprintln!("Warning: non-interactive stdin.");
}
// After reading, guard the indexing:
if need_instrut.is_empty() { /* skip instructions or default */ } Type guard
// Guard the [..1] indexing with a safe check
fn wants_instructions(input: &str) -> bool {
input.trim_start().to_ascii_lowercase().starts_with('y')
} Try / catch
match io::stdin().read_line(&mut need_instrut) {
Ok(0) => { /* skip instructions */ }
Ok(_) => { /* safe-index with starts_with */ }
Err(e) => { eprintln!("{}", e); return; }
} Prevention
- Never use raw slice indexing ([..1]) on user input — use starts_with or chars().next().
- Handle EOF at the very first input prompt as a normal condition.
- Guard all string indexing operations with length checks.
When it happens
Trigger: Stdin returns `Err` or EOF at the instructions prompt. If stdin is closed/redirected, this is the first panic the player hits, before the game even starts. An empty line (just Enter) returns `Ok` with content `"\n"`, so it does *not* trigger this panic — instead it triggers the `[..1]` indexing panic on line 20.
Common situations: Non-interactive execution. Running in CI. Stdin redirected from `/dev/null`. No TTY allocated (Docker without `-it`). Process spawned by a GUI without stdin wiring.
Related errors
AI-assisted analysis of coding-horror/basic-computer-games@5301155192 (2026-08-13).
Data as JSON: /api/errors/f2199b075f413ef7.
Report an issue: GitHub.