{"record":{"id":"f9c7d6cd0e5fdde4","repo":"coding-horror/basic-computer-games","slug":"failed-to-read-line","errorCode":null,"errorMessage":"Failed to read line","messagePattern":"Failed to read line","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"08_Batnum/rust/src/main.rs","lineNumber":134,"sourceCode":"    fn get_min_max() -> (usize, usize) {\n        print!(\"ENTER MIN \");\n        let _ = io::stdout().flush();\n        let min = read_input_integer();\n\n        print!(\"ENTER MAX \");\n        let _ = io::stdout().flush();\n        let max = read_input_integer();\n\n        (min, max)\n    }\n}\n\nfn read_input_integer() -> usize {\n    loop {\n        let mut input = String::new();\n        io::stdin()\n            .read_line(&mut input)\n            .expect(\"Failed to read line\");\n        match input.trim().parse::<usize>() {\n            Ok(num) => {\n                if num == 0 {\n                    print!(\"Must be greater than zero \");\n                    let _ = io::stdout().flush();\n                    continue;\n                }\n                return num;\n            }\n            Err(_err) => {\n                print!(\"Please enter a number greater than zero \");\n                let _ = io::stdout().flush();\n                continue;\n            }\n        }\n    }\n}\n","sourceCodeStart":116,"sourceCodeEnd":152,"githubUrl":"https://github.com/coding-horror/basic-computer-games/blob/5301155192d91d74d337899cecc59dbda59c4c17/08_Batnum/rust/src/main.rs#L116-L152","documentation":"A panic via .expect(\"Failed to read line\") on io::stdin().read_line() in read_input_integer() of the Batnum Rust port, used to read the count of objects in a Nim-like game. read_line returns Err only on I/O failure (closed/exhausted stdin, broken pipe); invalid numeric text is handled separately by the parse branch which re-prompts. The expect converts any read error into a panic.","triggerScenarios":"stdin reaches EOF before a number is entered; stdin is closed or redirected from a stream that ends early; a broken pipe between the feeder and the process.","commonSituations":"Piping a fixture with too few lines; running under `< /dev/null`; CI harness that closes stdin once output stops.","solutions":["Ensure the piped input contains a numeric line for each call to read_input_integer.","Run interactively so stdin stays open.","Swap .expect for `match`/`?` that returns a default or exits on read error."],"exampleFix":"// before\nio::stdin().read_line(&mut input).expect(\"Failed to read line\");\n\n// after\nif io::stdin().read_line(&mut input).is_err() {\n    eprintln!(\"Input stream closed.\");\n    std::process::exit(1);\n}","handlingStrategy":"try-catch","validationCode":"// Detect that stdin is exhausted before relying on read_line\nuse std::io::IsTerminal;\nif !std::io::stdin().is_terminal() {\n    // ensure the input fixture still has lines\n}","typeGuard":null,"tryCatchPattern":"// Replace .expect with a match that exits cleanly\nmatch io::stdin().read_line(&mut input) {\n    Ok(0) | Err(_) => { eprintln!(\"Input closed.\"); std::process::exit(1); }\n    Ok(_) => { /* parse num */ }\n}","preventionTips":["Use match on read_line instead of .expect.","Size input fixtures to cover every prompt including repeats.","Handle Ok(0) (EOF) distinctly from parse errors."],"tags":["rust","stdin","io","panic","expect"],"backgroundTag":null,"analyzedSha":"5301155192d91d74d337899cecc59dbda59c4c17","analyzedAt":"2026-08-13T19:29:00.979Z","schemaVersion":2},"datasetVersion":"2026-08-14T00:17:13.853Z"}