BloopAI/vibe-kanban · error
Failed to read email
Error message
Failed to read email
What it means
`Input::interact_text()` from the dialoguer crate returns a Result; it errors when reading from stdin fails (e.g. no TTY, EOF, or interrupted terminal). The code expects success, so a failed interactive prompt panics with "Failed to read email" in the review CLI's `prompt_email` step.
Source
Thrown at crates/review/src/main.rs:78
println!("Full terms and conditions and privacy policy: https://review.fast/terms");
println!();
println!("Press Enter to accept and continue...");
let mut input = String::new();
std::io::stdin().read_line(&mut input).ok();
}
fn prompt_email(config: &mut config::Config) -> String {
use dialoguer::Input;
let mut input: Input<String> =
Input::new().with_prompt("Email address (we'll send a link to the review here, no spam)");
if let Some(ref saved_email) = config.email {
input = input.default(saved_email.clone());
}
let email: String = input.interact_text().expect("Failed to read email");
// Save email for next time
config.email = Some(email.clone());
if let Err(e) = config.save() {
debug!("Failed to save config: {}", e);
}
email
}
fn create_spinner(message: &str) -> ProgressBar {
let spinner = ProgressBar::new_spinner();
spinner.set_style(
ProgressStyle::default_spinner()
.template("{spinner:.green} {msg}")
.expect("Invalid spinner template"),
);
spinner.set_message(message.to_string());View on GitHub (pinned to 4deb7eca8f)
Solutions
- Detect non-interactive environments first (atty/is-terminal on stdin) and require the email via a CLI flag or config file instead of prompting
- Replace expect with match on interact_text(): on error, print a friendly message and exit with a nonzero code
- Support an --email argument or REVIEW_EMAIL env var so the prompt can be skipped entirely
- Allow retrying the prompt once before exiting
Example fix
// before
let email: String = input.interact_text().expect("Failed to read email");
// after
let email: String = input.interact_text()
.context("Could not read email from terminal. Pass --email or run interactively.")?; Defensive patterns
Strategy: validation
Validate before calling
if !std::io::stdin().is_terminal() {
eprintln!("No interactive terminal; pass --email or set REVIEW_EMAIL");
std::process::exit(1);
} Try / catch
let email = match input.interact_text() {
Ok(e) => e,
Err(e) => { eprintln!("Could not read email: {e}"); std::process::exit(1); }
}; Prevention
- Check for a TTY before prompting
- Offer --email flag / env var as non-interactive alternatives
- Save the email to config so later runs skip the prompt
- Handle Ctrl+D/EOF gracefully with a clear message
When it happens
Trigger: `prompt_email` runs and the terminal read fails: running non-interactively (CI, piped stdin like `echo | review`, no TTY), user presses Ctrl+D (EOF), or the terminal is closed mid-prompt.
Common situations: Running the PR review tool in CI or scripted environments without an interactive terminal; users piping input; Ctrl+C/Ctrl+D during the prompt; Windows console edge cases.
Related errors
- Invalid spinner template
- Default profiles v3 JSON is invalid
- request_id called for unsupported request variant
- handled non-session commands earlier
- Raw stream should only have Stdout/Stderr/Finished
AI-assisted analysis of BloopAI/vibe-kanban@4deb7eca8f (2026-08-29).
Data as JSON: /api/errors/add86a9d9d93a287.
Report an issue: GitHub.