{"record":{"id":"f627aba49e627d0a","repo":"coding-horror/basic-computer-games","slug":"failed-to-get-input","errorCode":null,"errorMessage":"Failed to get Input","messagePattern":"Failed to get Input","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"33_Dice/rust/src/main.rs","lineNumber":83,"sourceCode":"\n        // Continue the game\n        let reply = readinput(\"TRY AGAIN\").to_ascii_uppercase();\n        if reply.starts_with(\"Y\") || reply.eq(\"YES\") {\n            frequency = [0; 13];\n        } else {\n            playing = false;\n        }\n    }\n}\n\n// function for getting input on same line\nfn readinput(str: &str) -> String {\n    print!(\"\\n{}? \", str);\n    let mut input = String::new();\n    io::stdout().flush().unwrap();\n    io::stdin()\n        .read_line(&mut input)\n        .expect(\"Failed to get Input\");\n    input\n}\n","sourceCodeStart":65,"sourceCodeEnd":86,"githubUrl":"https://github.com/coding-horror/basic-computer-games/blob/5301155192d91d74d337899cecc59dbda59c4c17/33_Dice/rust/src/main.rs#L65-L86","documentation":"In 33_Dice, the readinput helper prints a labeled prompt, flushes stdout, then reads input via io::stdin().read_line(...).expect(\"Failed to get Input\"). All player input in the Dice game flows through this function. The panic triggers when stdin returns Err (EOF, broken pipe, invalid fd). Note: the preceding io::stdout().flush().unwrap() has the same fragility but is not the subject of this error.","triggerScenarios":"Any input prompt in the Dice game when stdin is at EOF or the read fails. Since readinput is the sole input function, exhausting piped input at any point crashes the game.","commonSituations":"Running the Dice game with scripted input that runs out, pressing Ctrl+D during a bet or roll prompt, or CI testing without sufficient input lines.","solutions":["Change readinput to return Option<String> and have callers handle None by exiting or using a default","Replace .expect() with .unwrap_or_default() so an I/O failure yields an empty string that callers can treat as invalid input","Return Result<String, io::Error> and use ? in callers"],"exampleFix":"// before\nfn readinput(str: &str) -> String {\n    print!(\"\\n{}? \", str);\n    let mut input = String::new();\n    io::stdout().flush().unwrap();\n    io::stdin()\n        .read_line(&mut input)\n        .expect(\"Failed to get Input\");\n    input\n}\n\n// after\nfn readinput(str: &str) -> Option<String> {\n    print!(\"\\n{}? \", str);\n    let _ = io::stdout().flush();\n    let mut input = String::new();\n    match io::stdin().read_line(&mut input) {\n        Ok(0) | Err(_) => None,\n        Ok(_) => Some(input),\n    }\n}","handlingStrategy":"fallback","validationCode":null,"typeGuard":null,"tryCatchPattern":"fn readinput(str: &str) -> Option<String> {\n    print!(\"\\n{}? \", str);\n    let _ = io::stdout().flush();\n    let mut input = String::new();\n    match io::stdin().read_line(&mut input) {\n        Ok(0) | Err(_) => None,\n        Ok(_) => Some(input),\n    }\n}","preventionTips":["Return Option<String> from input helpers so callers can use if let Some(input) = readinput(...) and exit cleanly on None","Do not use .unwrap() on stdout().flush() — a flush failure should not prevent the game from attempting the read","Centralize all player input through one helper function to ensure consistent EOF handling across the game"],"tags":["rust","stdin","read-line","panic","expect","io-error","eof","interactive","helper","cli"],"backgroundTag":null,"analyzedSha":"5301155192d91d74d337899cecc59dbda59c4c17","analyzedAt":"2026-08-13T19:29:00.979Z","schemaVersion":2},"datasetVersion":"2026-08-14T00:17:13.853Z"}