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

  1. Check the AI response contains a subcommand after 'f'/'flow' before calling normalize_command, and re-prompt otherwise
  2. Reject/handle malformed quoted suggestions by validating shell_words::split succeeded (currently silently falls back to whitespace split)
  3. Ask the model for structured 'cmd: <subcommand> <args>' output and validate non-empty args
  4. 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

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


AI-assisted analysis of nikivdev/code@a747e741ae (2026-09-01). Data as JSON: /api/errors/ba8ffd46b9c9f5bc. Report an issue: GitHub.