{"record":{"id":"ba8ffd46b9c9f5bc","repo":"nikivdev/code","slug":"command-is-incomplete","errorCode":null,"errorMessage":"Command '{}' is incomplete.","messagePattern":"Command '(.+?)' is incomplete\\.","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"src/ask.rs","lineNumber":501,"sourceCode":"\nfn normalize_command(raw: &str, valid_subcommands: &HashSet<String>) -> Result<String> {\n    let mut cmd = raw.trim().trim_matches('`').trim().to_string();\n    if cmd.starts_with(\"cmd:\") {\n        cmd = cmd.trim_start_matches(\"cmd:\").trim().to_string();\n    } else if cmd.starts_with(\"command:\") {\n        cmd = cmd.trim_start_matches(\"command:\").trim().to_string();\n    }\n\n    if cmd.starts_with(\"flow \") {\n        cmd = format!(\"f {}\", cmd.trim_start_matches(\"flow \").trim());\n    } else if !cmd.starts_with(\"f \") {\n        cmd = format!(\"f {}\", cmd);\n    }\n\n    let tokens = shell_words::split(&cmd)\n        .unwrap_or_else(|_| cmd.split_whitespace().map(|s| s.to_string()).collect());\n    if tokens.len() < 2 {\n        bail!(\"Command '{}' is incomplete.\", cmd);\n    }\n    let sub = tokens[1].to_ascii_lowercase();\n    if !valid_subcommands.contains(&sub) {\n        bail!(\"AI returned unknown command '{}'.\", cmd);\n    }\n\n    Ok(cmd)\n}\n\nfn is_command_like(raw: &str, valid_subcommands: &HashSet<String>) -> bool {\n    let first = raw\n        .split_whitespace()\n        .next()\n        .unwrap_or(\"\")\n        .trim()\n        .to_ascii_lowercase();\n    if first.is_empty() {\n        return false;","sourceCodeStart":483,"sourceCodeEnd":519,"githubUrl":"https://github.com/nikivdev/code/blob/a747e741ae92c09071d0ae946ab48488adcff1ce/src/ask.rs#L483-L519","documentation":"normalize_command coerces a suggestion into the canonical 'f <subcommand> ...' form, splitting it with shell_words. If after tokenizing there are fewer than 2 tokens (i.e. only 'f' itself, no subcommand or args), the command cannot be dispatched and this error is thrown.","triggerScenarios":"parse_ask_response or parse_structured_line passes a response like 'f', 'f `', 'cmd: f', or a string whose shell_words::split collapses to a single token (e.g. unterminated quote producing the fallback whitespace split).","commonSituations":"AI emits the bare prefix 'f' or 'flow' with no subcommand; quoted suggestion like 'f \"' confuses the shell-word parser; the 'cmd:'/'command:' prefix contained only whitespace after stripping.","solutions":["Check the AI response contains a subcommand after 'f'/'flow' before calling normalize_command, and re-prompt otherwise","Reject/handle malformed quoted suggestions by validating shell_words::split succeeded (currently silently falls back to whitespace split)","Ask the model for structured 'cmd: <subcommand> <args>' output and validate non-empty args","Fall back to listing valid subcommands for the user when the suggestion is incomplete"],"exampleFix":"// before\nlet tokens = shell_words::split(&cmd)\n    .unwrap_or_else(|_| cmd.split_whitespace().map(|s| s.to_string()).collect());\nif tokens.len() < 2 {\n    bail!(\"Command '{}' is incomplete.\", cmd);\n}\n// after\nlet tokens = shell_words::split(&cmd)\n    .with_context(|| format!(\"could not tokenize command '{}'\", cmd))?;\nif tokens.len() < 2 {\n    bail!(\"Command '{}' is incomplete. Expected: f <subcommand> [args]\", cmd);\n}","handlingStrategy":"validation","validationCode":"fn suggestion_is_complete(raw: &str) -> bool {\n    let cmd = raw.trim().trim_matches('`');\n    let body = cmd.trim_start_matches(\"cmd:\").trim_start_matches(\"command:\").trim();\n    let body = body.strip_prefix(\"flow \").unwrap_or_else(|| body.strip_prefix(\"f \").unwrap_or(body));\n    !body.trim().is_empty()\n}","typeGuard":null,"tryCatchPattern":"match normalize_command(raw, &valid_subcommands) {\n    Err(e) if e.to_string().contains(\"is incomplete\") => eprintln!(\"Suggestion lacked a subcommand; skipping.\"),\n    other => other,\n}","preventionTips":["Check for a non-empty subcommand before calling normalize_command","Avoid AI suggestions with unbalanced quotes that break shell_words::split","Require structured 'cmd: <subcommand> <args>' answers from the model","Don't silently fall back to whitespace splitting on tokenizer failure"],"tags":["cli","input-validation","parsing"],"backgroundTag":"incomplete-command-input","analyzedSha":"a747e741ae92c09071d0ae946ab48488adcff1ce","analyzedAt":"2026-09-01T22:43:55.719Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}