{"record":{"id":"a27d511129ae2890","repo":"coding-horror/basic-computer-games","slug":"failed-to-read-line-a27d51","errorCode":null,"errorMessage":"Failed to read line.","messagePattern":"Failed to read line\\.","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"96_Word/rust/src/main.rs","lineNumber":39,"sourceCode":"            game_over = game.tick();\n        }\n\n        quit = !play_again();\n    }\n}\n\nfn play_again() -> bool {\n    let mut again = true;\n    let mut valid_response = false;\n\n    while valid_response == false {\n        println!(\"Want to play again? (Y/n)\");\n\n        let mut response = String::new();\n\n        io::stdin()\n            .read_line(&mut response)\n            .expect(\"Failed to read line.\");\n\n        match response.trim().to_uppercase().as_str() {\n            \"Y\" | \"YES\" => valid_response = true,\n            \"N\" | \"NO\" => {\n                again = false;\n                valid_response = true;\n            }\n            _ => (),\n        }\n    }\n\n    again\n}\n","sourceCodeStart":21,"sourceCodeEnd":53,"githubUrl":"https://github.com/coding-horror/basic-computer-games/blob/5301155192d91d74d337899cecc59dbda59c4c17/96_Word/rust/src/main.rs#L21-L53","documentation":"The play_again function for the Word game loops with a while !valid_response until the user enters a valid Y/N answer. Inside the loop, read_line().expect(\"Failed to read line.\") panics on io::Error. On EOF (Ok(0)) the empty string matches none of the Y/YES/N/NO arms, so the while-loop re-prompts forever — a busy-spin identical to the Tower of Hanoi prompt issue but confined to the play-again gate.","triggerScenarios":"Piped input that closes after a game round ends but before the play-again prompt. Ctrl-D at the 'Want to play again?' prompt (triggers infinite loop, not panic). A broken stdin pipe.","commonSituations":"Automated testing that pipes one full game's worth of input but no play-again answer. Non-interactive execution with /dev/null stdin (infinite loop). Docker without -it.","solutions":["Match on read_line; on Ok(0) set again=false and break the loop (treat EOF as 'no').","On Err(e), eprintln the error, set again=false, and break to exit cleanly.","Add an EOF guard: if the input string is empty after read_line, break with again=false.","For testing, append a 'n\\n' or 'y\\n' line after every game round's input."],"exampleFix":"// before\nio::stdin()\n    .read_line(&mut response)\n    .expect(\"Failed to read line.\");\n\n// after\nmatch io::stdin().read_line(&mut response) {\n    Ok(0) => { again = false; valid_response = true; }\n    Ok(_) => {}\n    Err(e) => {\n        eprintln!(\"Input error: {e}\");\n        again = false;\n        valid_response = true;\n    }\n}","handlingStrategy":"try-catch","validationCode":"// Break the play-again loop on EOF to prevent infinite spin\nmatch io::stdin().read_line(&mut response) {\n    Ok(0) => { again = false; valid_response = true; }  // EOF: exit\n    Err(e) => {\n        eprintln!(\"Input error: {e}\");\n        again = false;\n        valid_response = true;\n    }\n    Ok(_) => { /* proceed with Y/N match */ }\n}","typeGuard":null,"tryCatchPattern":"// Inside the while !valid_response loop\nmatch io::stdin().read_line(&mut response) {\n    Ok(n) if n > 0 => {\n        match response.trim().to_uppercase().as_str() {\n            \"Y\" | \"YES\" => { valid_response = true; }\n            \"N\" | \"NO\" => { again = false; valid_response = true; }\n            _ => {}  // re-prompt\n        }\n    }\n    _ => { again = false; valid_response = true; }  // EOF/error: exit\n}","preventionTips":["Break validation loops on EOF — sticky stdin causes infinite re-prompting otherwise.","Set valid_response=true on EOF to ensure the while-loop terminates.","Test play-again prompts by piping exactly one game's input and then closing stdin.","Treat EOF as 'no' (again=false) since a disconnected user cannot continue playing."],"tags":["rust","io","stdin","panic","play-again","infinite-loop","word-game"],"backgroundTag":null,"analyzedSha":"5301155192d91d74d337899cecc59dbda59c4c17","analyzedAt":"2026-08-13T19:29:00.979Z","schemaVersion":2},"datasetVersion":"2026-08-14T00:17:13.853Z"}