denisidoro/navi · error · anyhow

No command and options captured in the line

Error message

No command and options captured in the line `{}`

What it means

Thrown by `parse_variable_line` in src/parser.rs when capture group 2 (the command-and-options section after the variable) is missing from the regex match. The variable was found, but there is no command portion to execute.

Solutions

  1. Add the command after the variable and colon, e.g. `#my-var: cat file.txt`
  2. Remove the now-empty variable definition if it is no longer needed
  3. Check the file for truncated lines and restore the full definition

Example fix

// before
#my-var:
// after
#my-var: cat file.txt --- --prompt "Pick:"
Defensive patterns

Strategy: validation

Validate before calling

let has_command = |line: &str| {
    line.split_once(':').map_or(false, |(_, rhs)| !rhs.trim().is_empty())
};
// require has_command(line) before parsing

Prevention

When it happens

Trigger: A variable line matching the regex for the variable part but lacking the command after the colon, e.g. `#my-var:` with nothing following, or a line where the separator layout prevents group 2 from capturing.

Common situations: Config lines where the command was deleted but the variable definition kept; line truncation from editors or copy-paste; writing only options without a command before `---`.

Related errors


AI-assisted analysis of denisidoro/navi@f7330b9ad5 (2026-09-03). Data as JSON: /api/errors/040e2751e481bb1a. Report an issue: GitHub.

Appendix: source

Thrown at src/parser.rs:98

        (false, true) => SuggestionType::SingleSelection,
    };
    opts.suggestion_type = suggestion_type;

    Ok(opts)
}

fn parse_variable_line(line: &str) -> Result<(&str, &str, Option<FinderOpts>)> {
    let caps = VAR_LINE_REGEX
        .captures(line)
        .ok_or_else(|| anyhow!("No variables, command, and options found in the line `{}`", line))?;
    let variable = caps
        .get(1)
        .ok_or_else(|| anyhow!("No variable captured in the line `{}`", line))?
        .as_str()
        .trim();
    let mut command_plus_opts = caps
        .get(2)
        .ok_or_else(|| anyhow!("No command and options captured in the line `{}`", line))?
        .as_str()
        .split("---");
    let command = command_plus_opts
        .next()
        .ok_or_else(|| anyhow!("No command captured in the line `{}`", line))?;
    let command_options = command_plus_opts.next().map(parse_opts).transpose()?;
    Ok((variable, command, command_options))
}

fn without_prefix(line: &str) -> String {
    // The prefix character (#, %, @) is always 1-byte ASCII.
    // Skip it and let trim() handle any whitespace separator, including
    // multi-byte whitespace like non-breaking space (\u{a0}).
    line.get(1..).unwrap_or("").trim().to_string()
}

#[derive(Clone, Default)]
pub struct FilterOpts {

View on GitHub (pinned to f7330b9ad5)