{"record":{"id":"ab9aee8fd9c7df61","repo":"coding-horror/basic-computer-games","slug":"no-valid-input","errorCode":null,"errorMessage":"No valid input","messagePattern":"No valid input","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"58_Love/rust/src/main.rs","lineNumber":63,"sourceCode":"        vec![6, 6, 9, 3, 12, 6, 7, 1, 10],\r\n        vec![7, 6, 7, 3, 13, 6, 6, 2, 10],\r\n        vec![7, 6, 7, 3, 13, 14, 10],\r\n        vec![8, 6, 5, 3, 14, 6, 6, 2, 10],\r\n        vec![8, 6, 5, 3, 14, 6, 7, 1, 10],\r\n        vec![9, 6, 3, 3, 15, 6, 16, 1, 1],\r\n        vec![9, 6, 3, 3, 15, 6, 15, 2, 1],\r\n        vec![10, 6, 1, 3, 16, 6, 14, 3, 1],\r\n        vec![10, 10, 16, 6, 12, 5, 1],\r\n        vec![11, 8, 13, 27, 1],\r\n        vec![11, 8, 13, 27, 1],\r\n        vec![60],\r\n    ];\r\n\r\n    const ROW_LEN: usize = 60;\r\n    show_intro();\r\n\r\n    let mut input: String = String::new();\r\n    io::stdin().read_line(&mut input).expect(\"No valid input\");\r\n    let input = if input.len() == 1 {\r\n        \"LOVE\"\r\n    } else {\r\n        input.trim()\r\n    };\r\n    // repeat the answer to fill the whole line, we will show chunks of this when needed\r\n    let input = input.repeat(ROW_LEN / (input.len()) + 1);\r\n\r\n    // Now lets display the Love\r\n    print!(\"{}\", \"\\n\".repeat(9));\r\n    for row in data {\r\n        let mut print_or_pass = PrintOrPass::Print;\r\n        let mut current_start = 0;\r\n        for count in row {\r\n            match print_or_pass {\r\n                PrintOrPass::Print => {\r\n                    print!(\"{}\", &input[current_start..count + current_start]);\r\n                    print_or_pass = PrintOrPass::Pass;\r","sourceCodeStart":45,"sourceCodeEnd":81,"githubUrl":"https://github.com/coding-horror/basic-computer-games/blob/5301155192d91d74d337899cecc59dbda59c4c17/58_Love/rust/src/main.rs#L45-L81","documentation":"This panic is triggered by `.expect(\"No valid input\")` on `io::stdin().read_line()` in the Love program. The message is misleading — the failure is not about input *validity* (that is handled downstream by the `input.trim()` logic) but about `read_line` returning `Err` due to an I/O-level failure reading from stdin.","triggerScenarios":"Stdin is unavailable, closed, or returns an I/O error before any line is read. This happens before the program reaches the `input.repeat(ROW_LEN / input.len() + 1)` line, so the panic preempts the separate divide-by-zero risk on empty input. Common when the process inherits no stdin handle.","commonSituations":"Running inside Docker/CI without `-it` flags. Launching from a desktop launcher or IDE run configuration that does not allocate a terminal. Redirecting stdin from a broken pipe or a file that triggers an I/O error.","solutions":["Replace `.expect()` with a `match` that distinguishes `Ok(0)` (EOF) from genuine `Err`, exiting gracefully on EOF.","Add a pre-check or configuration option to read the word from a command-line argument or file when stdin is not interactive.","Wrap the entire read in a retry loop with a maximum attempt count for transient I/O errors."],"exampleFix":"// before\nio::stdin().read_line(&mut input).expect(\"No valid input\");\n\n// after\nlet bytes_read = io::stdin().read_line(&mut input);\nmatch bytes_read {\n    Ok(0) => { println!(\"No input received. Exiting.\"); return; }\n    Ok(_) => {}\n    Err(e) => { eprintln!(\"Failed to read input: {}\", e); return; }\n}","handlingStrategy":"try-catch","validationCode":"use std::io::IsTerminal;\nif !io::stdin().is_terminal() {\n    // Provide input via argument or file instead\n}","typeGuard":"fn safe_read_line() -> Option<String> {\n    let mut buf = String::new();\n    match io::stdin().read_line(&mut buf) {\n        Ok(0) | Err(_) => None,\n        Ok(_) => Some(buf.trim().to_string()),\n    }\n}","tryCatchPattern":"let mut input = String::new();\nmatch io::stdin().read_line(&mut input) {\n    Ok(0) => { println!(\"No input. Exiting.\"); return; }\n    Ok(_) => { /* proceed with input.trim() */ }\n    Err(e) => { eprintln!(\"{}\", e); return; }\n}","preventionTips":["Replace .expect() on read_line with Result matching in all CLI programs.","Handle EOF as a normal exit condition, not an error.","Guard against empty input before calling input.len()-dependent operations like repeat()."],"tags":["rust","stdin","io","panic","expect","misleading-message","cli-game"],"backgroundTag":null,"analyzedSha":"5301155192d91d74d337899cecc59dbda59c4c17","analyzedAt":"2026-08-13T19:29:00.979Z","schemaVersion":2},"datasetVersion":"2026-08-14T00:17:13.853Z"}