{"record":{"id":"8778041d963fdc4f","repo":"coding-horror/basic-computer-games","slug":"couldn-t-flush-stdout","errorCode":null,"errorMessage":"couldn't flush stdout","messagePattern":"couldn't flush stdout","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"24_Chemist/rust/src/lib.rs","lineNumber":96,"sourceCode":"        } else {\n            println!(\" Good job!  You may breathe now, but don't inhale the fumes!\");\n            println!();\n        }\n    }\n\n    //return to main\n    Ok(())\n}\n\n/// gets a string from user input\nfn get_string_from_user_input(prompt: &str) -> Result<String, Box<dyn Error>> {\n    //DATA\n    let mut raw_input = String::new();\n\n    //print prompt\n    print!(\"{}\", prompt);\n    //make sure it's printed before getting input\n    io::stdout().flush().expect(\"couldn't flush stdout\");\n\n    //read user input from standard input, and store it to raw_input, then return it or an error as needed\n    raw_input.clear(); //clear input\n    match io::stdin().read_line(&mut raw_input) {\n        Ok(_num_bytes_read) => return Ok(String::from(raw_input.trim())),\n        Err(err) => return Err(format!(\"ERROR: CANNOT READ INPUT!: {}\", err).into()),\n    }\n}\n/// generic function to get a number from the passed string (user input)\n/// pass a min lower  than the max to have minimum and maximum bounds\n/// pass a min higher than the max to only have a minimum bound\n/// pass a min equal   to  the max to only have a maximum bound\n/// \n/// Errors:\n/// no number on user input\nfn get_number_from_input<T:Display + PartialOrd + FromStr>(prompt: &str, min:T, max:T) -> Result<T, Box<dyn Error>> {\n    //DATA\n    let raw_input: String;","sourceCodeStart":78,"sourceCodeEnd":114,"githubUrl":"https://github.com/coding-horror/basic-computer-games/blob/5301155192d91d74d337899cecc59dbda59c4c17/24_Chemist/rust/src/lib.rs#L78-L114","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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"],"exampleFix":"// before\nprint!(\"{}\", prompt);\nio::stdout().flush().expect(\"couldn't flush stdout\");\n\n// after\nprint!(\"{}\", prompt);\nio::stdout().flush()?;","handlingStrategy":"try-catch","validationCode":"use std::io::IsTerminal;\nif !io::stdout().is_terminal() {\n    eprintln!(\"Warning: stdout is not a terminal; flush failures will be ignored.\");\n}","typeGuard":null,"tryCatchPattern":"match io::stdout().flush() {\n    Ok(()) => { /* prompt displayed */ }\n    Err(e) if e.kind() == std::io::ErrorKind::BrokenPipe => { /* ignore: downstream consumer exited */ }\n    Err(e) => return Err(e.into()),\n}","preventionTips":["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"],"tags":["rust","stdout","flush","panic","expect","io-error","broken-pipe","cli"],"backgroundTag":null,"analyzedSha":"5301155192d91d74d337899cecc59dbda59c4c17","analyzedAt":"2026-08-13T19:29:00.979Z","schemaVersion":2},"datasetVersion":"2026-08-14T00:17:13.853Z"}