{"record":{"id":"0af5da855ad6d887","repo":"getzola/zola","slug":"unable-to-read-from-stdin-for-confirmation","errorCode":null,"errorMessage":"unable to read from stdin for confirmation","messagePattern":"unable to read from stdin for confirmation","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"src/prompt.rs","lineNumber":15,"sourceCode":"use std::io::{self, BufRead, Write};\n\nuse url::Url;\n\nuse errors::{Result, anyhow};\n\n/// Wait for user input and return what they typed\nfn read_line() -> Result<String> {\n    let stdin = io::stdin();\n    let stdin = stdin.lock();\n    let mut lines = stdin.lines();\n    lines\n        .next()\n        .and_then(|l| l.ok())\n        .ok_or_else(|| anyhow!(\"unable to read from stdin for confirmation\"))\n}\n\n/// Ask a yes/no question to the user\npub fn ask_bool(question: &str, default: bool) -> Result<bool> {\n    print!(\"{} {}: \", question, if default { \"[Y/n]\" } else { \"[y/N]\" });\n    let _ = io::stdout().flush();\n    let input = read_line()?;\n\n    match &*input {\n        \"y\" | \"Y\" | \"yes\" | \"YES\" | \"true\" => Ok(true),\n        \"n\" | \"N\" | \"no\" | \"NO\" | \"false\" => Ok(false),\n        \"\" => Ok(default),\n        _ => {\n            println!(\"Invalid choice: '{input}'\");\n            ask_bool(question, default)\n        }\n    }\n}","sourceCodeStart":1,"sourceCodeEnd":33,"githubUrl":"https://github.com/getzola/zola/blob/61d30828217957120309db657950224edf9707e2/src/prompt.rs#L1-L33","documentation":"read_line in src/prompt.rs reads a single line from stdin to confirm an interactive prompt. It panics/aborts with this anyhow error when stdin yields no line at all — i.e. the stream is closed (EOF) or the read fails with an I/O error. The library throws it because a confirmation prompt cannot proceed without user input.","triggerScenarios":"Calling ask_bool or ask_url when stdin is closed, exhausted (e.g. stdin already consumed to EOF by an earlier read or piped input), or the underlying read returns an I/O error.","commonSituations":"Running the CLI non-interactively (CI pipelines, cron) with stdin at EOF or </dev/null; piping input that runs out of lines before the prompt; a terminal/PTY that detaches mid-run.","solutions":["Provide input on stdin (pipe a line such as 'y' or run interactively) so lines().next() returns Some.","Check for a non-interactive flag (e.g. --force / --yes) to skip confirmation prompts entirely.","In CI, use the tool's non-interactive mode instead of relying on a TTY prompt.","If embedding, ensure stdin is not closed/consumed before the prompt runs."],"exampleFix":"// before\necho -n | myapp deploy   # stdin at EOF -> error\n// after\nyes | myapp deploy       # or: myapp deploy --yes","handlingStrategy":"try-catch","validationCode":"// Rust: probe stdin before prompting\nuse std::io::IsTerminal;\nfn stdin_usable() -> bool { !std::io::stdin().is_terminal() || atty_ok() } // or check !stdin is at EOF via a peek\nif std::io::stdin().read_line(&mut probe).is_ok() && !probe.is_empty() { /* safe to prompt */ }","typeGuard":"fn stdin_has_input() -> bool {\n    use std::io::IsTerminal;\n    std::io::stdin().is_terminal() // false in CI/piped-EOF contexts -> skip prompting\n}","tryCatchPattern":"match ask_bool(\"continue?\", true) {\n    Ok(v) => /* proceed with v */,\n    Err(e) if e.to_string().contains(\"unable to read from stdin\") => /* assume default / skip prompt */,\n    Err(e) => return Err(e),\n}","preventionTips":["Run interactive commands in a real TTY or pipe explicit answers (yes | cmd).","Use the tool's non-interactive flag (--yes/--force) in CI.","Never pipe input shorter than the number of prompts.","Detect non-interactive environments early (isatty) and avoid prompts."],"tags":["stdin","io","cli","interactive-prompt"],"backgroundTag":"stdin-unavailable","analyzedSha":"61d30828217957120309db657950224edf9707e2","analyzedAt":"2026-09-03T14:39:09.727Z","contentChangedAt":"2026-09-03T14:39:09.727Z","schemaVersion":2},"datasetVersion":"2026-09-10T17:17:09.494Z"}