nikivdev/code · warning
Command '{}' is incomplete.
Error message
Command '{}' is incomplete. What it means
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.
Source
Thrown at src/ask.rs:501
fn normalize_command(raw: &str, valid_subcommands: &HashSet<String>) -> Result<String> {
let mut cmd = raw.trim().trim_matches('`').trim().to_string();
if cmd.starts_with("cmd:") {
cmd = cmd.trim_start_matches("cmd:").trim().to_string();
} else if cmd.starts_with("command:") {
cmd = cmd.trim_start_matches("command:").trim().to_string();
}
if cmd.starts_with("flow ") {
cmd = format!("f {}", cmd.trim_start_matches("flow ").trim());
} else if !cmd.starts_with("f ") {
cmd = format!("f {}", cmd);
}
let tokens = shell_words::split(&cmd)
.unwrap_or_else(|_| cmd.split_whitespace().map(|s| s.to_string()).collect());
if tokens.len() < 2 {
bail!("Command '{}' is incomplete.", cmd);
}
let sub = tokens[1].to_ascii_lowercase();
if !valid_subcommands.contains(&sub) {
bail!("AI returned unknown command '{}'.", cmd);
}
Ok(cmd)
}
fn is_command_like(raw: &str, valid_subcommands: &HashSet<String>) -> bool {
let first = raw
.split_whitespace()
.next()
.unwrap_or("")
.trim()
.to_ascii_lowercase();
if first.is_empty() {
return false;View on GitHub (pinned to a747e741ae)
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
Example fix
// before
let tokens = shell_words::split(&cmd)
.unwrap_or_else(|_| cmd.split_whitespace().map(|s| s.to_string()).collect());
if tokens.len() < 2 {
bail!("Command '{}' is incomplete.", cmd);
}
// after
let tokens = shell_words::split(&cmd)
.with_context(|| format!("could not tokenize command '{}'", cmd))?;
if tokens.len() < 2 {
bail!("Command '{}' is incomplete. Expected: f <subcommand> [args]", cmd);
} Defensive patterns
Strategy: validation
Validate before calling
fn suggestion_is_complete(raw: &str) -> bool {
let cmd = raw.trim().trim_matches('`');
let body = cmd.trim_start_matches("cmd:").trim_start_matches("command:").trim();
let body = body.strip_prefix("flow ").unwrap_or_else(|| body.strip_prefix("f ").unwrap_or(body));
!body.trim().is_empty()
} Try / catch
match normalize_command(raw, &valid_subcommands) {
Err(e) if e.to_string().contains("is incomplete") => eprintln!("Suggestion lacked a subcommand; skipping."),
other => other,
} Prevention
- 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
When it happens
Trigger: 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).
Common situations: 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.
Related errors
- Suggested command is incomplete.
- Relative path cannot be empty.
- Relative path must not be absolute.
- plan body is empty
- no queries provided
AI-assisted analysis of nikivdev/code@a747e741ae (2026-09-01).
Data as JSON: /api/errors/ba8ffd46b9c9f5bc.
Report an issue: GitHub.