Hmbown/CodeWhale · warning

Selection out of range

Error message

Selection out of range

What it means

After parsing the input as a number, prompt_choice indexes the options list with n-1. If the number is valid but outside 1..=options.len(), the .get() returns None and 'Selection out of range' is thrown.

Solutions

  1. Enter a number between 1 and the number of displayed options
  2. Re-read the printed menu — option counts may differ from memory
  3. For scripts, count the options list before computing the index
  4. Press Enter on empty input to abort cleanly if no option fits

Example fix

// before
Selection: 7   # but only 5 options
// after
Selection: 5   # within 1..=len(options)
Defensive patterns

Strategy: validation

Validate before calling

let n: usize = input.trim().parse()?;
let valid = n >= 1 && n <= options.len();
if !valid { eprintln!("Pick 1..={}", options.len()); }

Try / catch

match prompt_choice(&prompt, &options) {
    Err(e) if e.to_string().contains("out of range") => {
        eprintln!("Choose 1-{}", options.len());
        prompt_choice(&prompt, &options)
    }
    other => other,
}

Prevention

When it happens

Trigger: Typing a number larger than the number of choices (or 0) at a resolve_cloud/resolve_bridge/resolve_provider prompt.

Common situations: Users guessing option numbers without reading the list, choosing item N+1 after the list shrank in a new version, or scripted input computed from an outdated menu.

Related errors


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

Appendix: source

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

    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::*;

    #[test]
    fn generated_token_is_long_and_hex() {
        let t = generate_runtime_token();
        assert_eq!(t.len(), 64, "two simple uuids = 64 hex chars");

View on GitHub (pinned to 73e0f67d83)