{"record":{"id":"58bced878394b189","repo":"Hmbown/CodeWhale","slug":"selection-out-of-range-58bced","errorCode":null,"errorMessage":"Selection out of range","messagePattern":"Selection out of range","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"crates/tui/src/remote_setup/mod.rs","lineNumber":261,"sourceCode":"    for (idx, opt) in options.iter().enumerate() {\n        println!(\"  {:>2}. {}\", idx + 1, opt);\n    }\n    print!(\"Enter a number: \");\n    io::stdout().flush()?;\n\n    let mut input = String::new();\n    io::stdin().read_line(&mut input)?;\n    let input = input.trim();\n    if input.is_empty() {\n        bail!(\"No selection made.\");\n    }\n    let n: usize = input\n        .parse()\n        .map_err(|_| anyhow::anyhow!(\"Invalid input: {input}\"))?;\n    options\n        .get(n.saturating_sub(1))\n        .map(|_| n - 1)\n        .ok_or_else(|| anyhow::anyhow!(\"Selection out of range\"))\n}\n\n/// Generate a runtime token from two random v4 UUIDs (OS CSPRNG via uuid),\n/// matching the existing token-generation pattern in this crate.\nfn generate_runtime_token() -> String {\n    let a = uuid::Uuid::new_v4().simple().to_string();\n    let b = uuid::Uuid::new_v4().simple().to_string();\n    format!(\"{a}{b}\")\n}\n\n#[cfg(test)]\nmod tests {\n    use super::*;\n\n    #[test]\n    fn generated_token_is_long_and_hex() {\n        let t = generate_runtime_token();\n        assert_eq!(t.len(), 64, \"two simple uuids = 64 hex chars\");","sourceCodeStart":243,"sourceCodeEnd":279,"githubUrl":"https://github.com/Hmbown/CodeWhale/blob/73e0f67d83c59909b571efdfc88c4bc28c309cb1/crates/tui/src/remote_setup/mod.rs#L243-L279","documentation":"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.","triggerScenarios":"Typing a number larger than the number of choices (or 0) at a resolve_cloud/resolve_bridge/resolve_provider prompt.","commonSituations":"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.","solutions":["Enter a number between 1 and the number of displayed options","Re-read the printed menu — option counts may differ from memory","For scripts, count the options list before computing the index","Press Enter on empty input to abort cleanly if no option fits"],"exampleFix":"// before\nSelection: 7   # but only 5 options\n// after\nSelection: 5   # within 1..=len(options)","handlingStrategy":"validation","validationCode":"let n: usize = input.trim().parse()?;\nlet valid = n >= 1 && n <= options.len();\nif !valid { eprintln!(\"Pick 1..={}\", options.len()); }","typeGuard":null,"tryCatchPattern":"match prompt_choice(&prompt, &options) {\n    Err(e) if e.to_string().contains(\"out of range\") => {\n        eprintln!(\"Choose 1-{}\", options.len());\n        prompt_choice(&prompt, &options)\n    }\n    other => other,\n}","preventionTips":["Count the listed options before choosing","Remember selection is 1-based; 0 is invalid","Re-print the menu when option counts may have changed","In scripts, derive the index from the options list length"],"tags":["cli","input-validation","interactive","range-check"],"backgroundTag":"index-out-of-range","analyzedSha":"73e0f67d83c59909b571efdfc88c4bc28c309cb1","analyzedAt":"2026-09-22T01:30:00.501Z","contentChangedAt":"2026-09-22T01:30:00.501Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}