rtk-ai/rtk · error

invalid nextest starting regex

Error message

invalid nextest starting regex

What it means

Panic from `.expect("invalid nextest starting regex")` after `regex::Regex::new` for the `Starting N tests across M binaries` pattern in `filter_cargo_nextest` (src/cmds/rust/cargo_cmd.rs). Same class as the summary-regex panic: the regex crate rejects a syntactically invalid pattern and the expect converts it into an abort on the first invocation of the filter.

Solutions

  1. Correct the regex literal syntax and re-run `cargo test filter_cargo_nextest`.
  2. Move the regex into a `LazyLock<Regex>` static so compilation happens once and never on the per-call hot path.
  3. Adopt the fallback pattern (return a Result and run the raw command) if regex construction can ever fail at runtime.

Example fix

// before
let starting_re = regex::Regex::new(r"Starting \d+ tests? across (\d+) binar(?:y|ies)")
    .expect("invalid nextest starting regex");
// after
static STARTING_RE: LazyLock<Regex> = LazyLock::new(|| {
    Regex::new(r"Starting \d+ tests? across (\d+) binar(?:y|ies)")
        .expect("invalid nextest starting regex")
});
Defensive patterns

Strategy: try-catch

Validate before calling

// validate every hardcoded pattern at startup or in tests
#[test]
fn starting_regex_is_valid() {
    regex::Regex::new(r"Starting \d+ tests? across (\d+) binar(?:y|ies)").unwrap();
}

Try / catch

let starting_re = match regex::Regex::new(STARTING_PAT) {
    Ok(re) => re,
    Err(e) => panic!("invalid nextest starting regex: {e}"), // keep message
};

Prevention

When it happens

Trigger: A syntax error introduced into the hardcoded starting-line pattern (e.g. `binar(?:y|ies)` group corrupted, dangling `\d+` escape, unclosed alternation); the panic surfaces when `filter_cargo_nextest` is first called by its unit tests.

Common situations: Manual edits matching a new cargo-nextest banner format, copy-paste mistakes breaking the `(?:y|ies)` group, or accidental removal of a closing parenthesis during refactoring.

Related errors


AI-assisted analysis of rtk-ai/rtk@0924356b4c (2026-09-19). Data as JSON: /api/errors/d861c9361acc0e38. Report an issue: GitHub.

Appendix: source

Thrown at src/cmds/rust/cargo_cmd.rs:639

    }
    let mut block = header.clone();
    if !body.is_empty() {
        block.push('\n');
        block.push_str(&body.join("\n"));
    }
    failures.push(block);
    header.clear();
    body.clear();
}

/// Filter cargo nextest output - show failures + compact summary
fn filter_cargo_nextest(output: &str) -> String {
    let summary_re = regex::Regex::new(
        r"Summary \[\s*([\d.]+)s\]\s+(\d+) tests? run:\s+(\d+) passed(?:,\s+(\d+) failed)?(?:,\s+(\d+) skipped)?"
    ).expect("invalid nextest summary regex");

    let starting_re = regex::Regex::new(r"Starting \d+ tests? across (\d+) binar(?:y|ies)")
        .expect("invalid nextest starting regex");

    let mut failures: Vec<String> = Vec::new();
    let mut in_failure_block = false;
    let mut past_summary = false;
    let mut current_failure_header = String::new();
    let mut current_failure_body = Vec::new();
    let mut summary_line = String::new();
    let mut binaries: u32 = 0;
    let mut has_cancel_line = false;

    for line in output.lines() {
        let trimmed = line.trim();

        // Strip compilation noise
        if trimmed.starts_with("Compiling")
            || trimmed.starts_with("Downloading")
            || trimmed.starts_with("Downloaded")
            || trimmed.starts_with("Finished")

View on GitHub (pinned to 0924356b4c)