Hmbown/CodeWhale · warning

Invalid input

Error message

Invalid input: {input}

What it means

prompt_choice parses interactive menu input as a usize index. Any non-empty input that is not a valid unsigned integer (e.g. letters, negative numbers, floats) produces this error; empty input produces a separate 'No selection made' error.

Solutions

  1. Enter the numeric option number shown next to the choice (1-based)
  2. Trim whitespace/paste artifacts and retry
  3. Only digits are accepted — no letters, signs, or decimals
  4. For automation, pipe the index (e.g. `echo 2 |`) rather than the option name

Example fix

// before
Cloud: aws
// after
Cloud: 2   # numeric position of 'aws' in the list
Defensive patterns

Strategy: try-catch

Validate before calling

let t = input.trim();
if t.is_empty() || t.parse::<usize>().is_err() {
    eprintln!("Enter a numeric option, e.g. 1");
}

Try / catch

match prompt_choice(&prompt, &options) {
    Err(e) if e.to_string().starts_with("Invalid input") => {
        // re-prompt once with a hint
        eprintln!("{e} — enter the option's number");
        prompt_choice(&prompt, &options)
    }
    other => other,
}

Prevention

When it happens

Trigger: At a remote setup prompt, typing text or a malformed number instead of the numeric option number (e.g. 'aws', '1.5', '-1', or a number with stray characters).

Common situations: Users typing the option's name instead of its number, pasting values with whitespace/characters, keyboard locale issues, or automated input feeding wrong tokens.

Understand the failure class

Background: "Invalid ... format", "must be in format X", "does not look like a ..." — invalid argument format errors across CLI tools and libraries — this error's family across 17 libraries.

Related errors


AI-assisted analysis of Hmbown/CodeWhale@73e0f67d83 (2026-09-22). Data as JSON: /api/errors/b811e621bae4e98c. Report an issue: GitHub.

Appendix: source

Thrown at crates/tui/src/remote_setup/mod.rs:257

/// Print a numbered menu, read a 1-based selection from stdin, return the index.
fn prompt_choice(title: &str, options: &[String]) -> Result<usize> {
    println!();
    println!("{title}:");
    for (idx, opt) in options.iter().enumerate() {
        println!("  {:>2}. {}", idx + 1, opt);
    }
    print!("Enter a number: ");
    io::stdout().flush()?;

    let mut input = String::new();
    io::stdin().read_line(&mut input)?;
    let input = input.trim();
    if input.is_empty() {
        bail!("No selection made.");
    }
    let n: usize = input
        .parse()
        .map_err(|_| anyhow::anyhow!("Invalid input: {input}"))?;
    options
        .get(n.saturating_sub(1))
        .map(|_| n - 1)
        .ok_or_else(|| anyhow::anyhow!("Selection out of range"))
}

/// Generate a runtime token from two random v4 UUIDs (OS CSPRNG via uuid),
/// matching the existing token-generation pattern in this crate.
fn generate_runtime_token() -> String {
    let a = uuid::Uuid::new_v4().simple().to_string();
    let b = uuid::Uuid::new_v4().simple().to_string();
    format!("{a}{b}")
}

#[cfg(test)]
mod tests {
    use super::*;

View on GitHub (pinned to 73e0f67d83)