{"record":{"id":"c53508e1f4f55aaf","repo":"coding-horror/basic-computer-games","slug":"cannot-read-input","errorCode":null,"errorMessage":"CANNOT READ INPUT!","messagePattern":"CANNOT READ INPUT!","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"01_Acey_Ducey/rust/src/main.rs","lineNumber":121,"sourceCode":"    println!(\"CREATIVE COMPUTING - MORRISTOWN, NEW JERSEY\");\n    println!(\"ACEY-DUCEY IS PLAYED IN THE FOLLOWING MANNER\");\n    println!(\"THE DEALER (COMPUTER) DEALS TWO CARDS FACE UP\");\n    println!(\"YOU HAVE AN OPTION TO BET OR NOT BET DEPENDING\");\n    println!(\"ON WHETHER OR NOT YOU FEEL THE CARD WILL HAVE\");\n    println!(\"A VALUE BETWEEN THE FIRST TWO.\");\n    println!(\"IF YOU DO NOT WANT TO BET IN A ROUND, ENTER 0\");\n    println!(\"\\n\\n\");\n}\n\nfn get_bet(user_bank: u16) -> u16 {\n    loop {\n        println!(\"\\nWHAT IS YOUR BET? ENTER 0 IF YOU DON'T WANT TO BET (CTRL+C TO EXIT)\");\n        let bet: u16;\n        let mut input = String::new();\n\n        io::stdin()\n            .read_line(&mut input)\n            .expect(\"CANNOT READ INPUT!\");\n\n        match input.trim().parse::<u16>() {\n            Ok(i) => bet = i,\n            Err(e) => {\n                println!(\"CHECK YOUR INPUT! {}!\", e.to_string().to_uppercase());\n                continue;\n            }\n        };\n\n        match bet {\n            bet if bet <= user_bank => return bet,\n            _ => {\n                println!(\"\\nSORRY, MY FRIEND, BUT YOU BET TOO MUCH.\");\n                println!(\"YOU HAVE ONLY {} DOLLARS TO BET.\", user_bank);\n            }\n        };\n    }\n}","sourceCodeStart":103,"sourceCodeEnd":139,"githubUrl":"https://github.com/coding-horror/basic-computer-games/blob/5301155192d91d74d337899cecc59dbda59c4c17/01_Acey_Ducey/rust/src/main.rs#L103-L139","documentation":"A panic via .expect(\"CANNOT READ INPUT!\") on io::stdin().read_line() in get_bet() of the Acey Ducey Rust port. read_line returns Err only when stdin itself is unavailable/closed (EOF on a closed pipe, redirected input exhausted, or a broken pipe), not on malformed text. The expect turns any such I/O failure into an immediate process abort.","triggerScenarios":"Running the binary with stdin closed or redirected from an empty/exhausted file or pipe; piping input that ends before the bet prompt is answered; running under a harness that closes stdin early.","commonSituations":"Automated testing with insufficient piped input; running via `echo '' | ./game` where the stream ends; CI environments with no TTY and truncated input fixtures.","solutions":["Provide enough lines on stdin to answer every prompt interactively expected by the game.","Run the program in an interactive terminal instead of piping a too-short stream.","Replace .expect with graceful handling: match on the Result and exit cleanly on EOF."],"exampleFix":"// before\nio::stdin().read_line(&mut input).expect(\"CANNOT READ INPUT!\");\n\n// after: handle EOF gracefully\nif io::stdin().read_line(&mut input).is_err() {\n    println!(\"\\nInput closed. Goodbye!\");\n    std::process::exit(0);\n}","handlingStrategy":"try-catch","validationCode":"// Rust: detect EOF/closed stdin before expecting a read\nuse std::io::IsTerminal;\nif !std::io::stdin().is_terminal() {\n    // ensure piped input has data; otherwise exit early\n}","typeGuard":null,"tryCatchPattern":"// Replace .expect with graceful handling\nmatch io::stdin().read_line(&mut input) {\n    Ok(_) => { /* parse bet */ }\n    Err(_) => { println!(\"Input closed. Exiting.\"); std::process::exit(0); }\n}","preventionTips":["Use match on read_line's Result instead of .expect for user-facing input.","When piping input, supply one line per prompt.","Test stdin-exhaustion paths explicitly in CI."],"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"}