coding-horror/basic-computer-games · error
couldn't flush stdout
Error message
couldn't flush stdout
What it means
In 24_Chemist, get_string_from_user_input calls io::stdout().flush() after print! to force the prompt text to appear before read_line blocks. The .expect("couldn't flush stdout") panics if the OS flush syscall returns Err. This is a std::io::Error propagated when stdout's file descriptor is invalid, the downstream pipe consumer has exited, or the terminal device is unavailable.
Source
Thrown at 24_Chemist/rust/src/lib.rs:96
} else {
println!(" Good job! You may breathe now, but don't inhale the fumes!");
println!();
}
}
//return to main
Ok(())
}
/// gets a string from user input
fn get_string_from_user_input(prompt: &str) -> Result<String, Box<dyn Error>> {
//DATA
let mut raw_input = String::new();
//print prompt
print!("{}", prompt);
//make sure it's printed before getting input
io::stdout().flush().expect("couldn't flush stdout");
//read user input from standard input, and store it to raw_input, then return it or an error as needed
raw_input.clear(); //clear input
match io::stdin().read_line(&mut raw_input) {
Ok(_num_bytes_read) => return Ok(String::from(raw_input.trim())),
Err(err) => return Err(format!("ERROR: CANNOT READ INPUT!: {}", err).into()),
}
}
/// generic function to get a number from the passed string (user input)
/// pass a min lower than the max to have minimum and maximum bounds
/// pass a min higher than the max to only have a minimum bound
/// pass a min equal to the max to only have a maximum bound
///
/// Errors:
/// no number on user input
fn get_number_from_input<T:Display + PartialOrd + FromStr>(prompt: &str, min:T, max:T) -> Result<T, Box<dyn Error>> {
//DATA
let raw_input: String;View on GitHub (pinned to 5301155192)
Solutions
- Replace .expect() with the ? operator — the enclosing function already returns Result<String, Box<dyn Error>>, so propagation is zero-cost
- Replace print! + flush with print! and let read_line's blocking call naturally flush on most terminal implementations, or use a crate like rustyline that handles prompt display internally
- Use writeln!(io::stdout(), "{}", prompt) which writes a newline and is more likely to auto-flush, then trim the trailing newline from input
Example fix
// before
print!("{}", prompt);
io::stdout().flush().expect("couldn't flush stdout");
// after
print!("{}", prompt);
io::stdout().flush()?; Defensive patterns
Strategy: try-catch
Validate before calling
use std::io::IsTerminal;
if !io::stdout().is_terminal() {
eprintln!("Warning: stdout is not a terminal; flush failures will be ignored.");
} Try / catch
match io::stdout().flush() {
Ok(()) => { /* prompt displayed */ }
Err(e) if e.kind() == std::io::ErrorKind::BrokenPipe => { /* ignore: downstream consumer exited */ }
Err(e) => return Err(e.into()),
} Prevention
- Prefer the ? operator inside functions that already return Result instead of .expect()
- Use println! instead of print! + flush when a trailing newline is acceptable, as println! auto-flushes on most platforms
- Handle BrokenPipe separately from other I/O errors — a consumer exiting early is often not a fatal condition for a CLI game
When it happens
Trigger: Piping the game's stdout through a process that exits before the game finishes (cargo run | head -n 5), redirecting stdout to a closed file descriptor, or running in a sandbox/container where stdout is detached from a valid sink.
Common situations: CI pipelines that pipe game output through pagers or text filters, cargo run | less where the user presses q to quit the pager mid-game, Docker containers launched without a TTY, or automated test harnesses that close stdout on assertion failure.
Related errors
- Failed to flush to stdout.
- failed to flush
- Error reading from stdin
- Error reading line.
- ~~Failed reading line!~~
AI-assisted analysis of coding-horror/basic-computer-games@5301155192 (2026-08-13).
Data as JSON: /api/errors/8778041d963fdc4f.
Report an issue: GitHub.