{"record":{"id":"022a7b89fff0f879","repo":"coding-horror/basic-computer-games","slug":"cannot-read-input-022a7b","errorCode":null,"errorMessage":"CANNOT READ INPUT!","messagePattern":"CANNOT READ INPUT!","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"61_Math_Dice/rust/src/main.rs","lineNumber":115,"sourceCode":"    }\n\n    //bottom\n    println!(\" ----- \");\n}\n\n/**\n * gets a integer from user input\n */\nfn get_number_from_user_input(prompt: &str, error_message: &str, min:u8, max:u8) -> u8 {\n    //input loop\n    return loop {\n        let mut raw_input = String::new(); // temporary variable for user input that can be parsed later\n\n        //print prompt\n        println!(\"{}\", prompt);\n        //read user input from standard input, and store it to raw_input\n        //raw_input.clear(); //clear input\n        io::stdin().read_line(&mut raw_input).expect( \"CANNOT READ INPUT!\");\n\n        //from input, try to read a number\n        match raw_input.trim().parse::<u8>() {\n            Ok(i) => {\n                if i < min || i > max { //input out of desired range\n                    println!(\"{}  ({}-{})\", error_message, min,max);\n                    continue; // run the loop again\n                }\n                else {\n                    break i;// this escapes the loop, returning i\n                }\n            },\n            Err(e) => {\n                println!(\"{}  {}\", error_message, e.to_string().to_uppercase());\n                continue; // run the loop again\n            }\n        };\n    };","sourceCodeStart":97,"sourceCodeEnd":133,"githubUrl":"https://github.com/coding-horror/basic-computer-games/blob/5301155192d91d74d337899cecc59dbda59c4c17/61_Math_Dice/rust/src/main.rs#L97-L133","documentation":"This panic is triggered by `.expect(\"CANNOT READ INPUT!\")` on `io::stdin().read_line()` inside `get_number_from_user_input` in Math Dice (line 115). The function is typed to return `u8` and is designed to loop/retry on bad numeric input or out-of-range values, but the `.expect` converts any stdin I/O failure into a process crash.","triggerScenarios":"Stdin returns `Err` or EOF when the function tries to read a number. The parse and range checks (`raw_input.trim().parse::<u8>()`, `i < min || i > max`) all happen *after* `read_line` succeeds, so they cannot trigger this panic. This is purely an I/O-layer failure.","commonSituations":"Non-interactive execution. Input piped from a file that ends prematurely. Terminal closed or SSH dropped mid-game. Running under a process supervisor with no stdin.","solutions":["Change the return type to `Option<u8>` and return `None` on `Ok(0)` (EOF) or `Err`, letting callers decide.","Use `match` on `read_line`, printing an error and `continue`-ing the loop on transient errors, exiting on EOF.","Ensure piped input files contain enough numeric lines for all prompts in a game session."],"exampleFix":"// before\nio::stdin().read_line(&mut raw_input).expect(\"CANNOT READ INPUT!\");\n\n// after\nmatch io::stdin().read_line(&mut raw_input) {\n    Ok(0) => { println!(\"\\nInput closed.\"); std::process::exit(0); }\n    Ok(_) => {}\n    Err(e) => { eprintln!(\"Input error: {}\", e); continue; }\n}","handlingStrategy":"try-catch","validationCode":"use std::io::IsTerminal;\nif !io::stdin().is_terminal() {\n    eprintln!(\"Warning: stdin is not interactive.\");\n}","typeGuard":"fn get_number(prompt: &str, min: u8, max: u8) -> Option<u8> {\n    let mut buf = String::new();\n    println!(\"{}\", prompt);\n    match io::stdin().read_line(&mut buf) {\n        Ok(0) | Err(_) => None,\n        Ok(_) => buf.trim().parse::<u8>().ok().filter(|&n| n >= min && n <= max),\n    }\n}","tryCatchPattern":"match io::stdin().read_line(&mut raw_input) {\n    Ok(0) => { println!(\"Input closed.\"); std::process::exit(0); }\n    Ok(_) => { /* parse and validate range */ }\n    Err(e) => { eprintln!(\"{}\", e); continue; }\n}","preventionTips":["Return Option<T> from numeric input functions to signal EOF/errors.","Separate I/O failure handling from parse/range validation in the retry loop.","Provide sufficient piped input lines for all prompts during testing."],"tags":["rust","stdin","io","panic","expect","generic-function","cli-game"],"backgroundTag":null,"analyzedSha":"5301155192d91d74d337899cecc59dbda59c4c17","analyzedAt":"2026-08-13T19:29:00.979Z","schemaVersion":2},"datasetVersion":"2026-08-14T00:17:13.853Z"}