rtk-ai/rtk · critical
invalid ctest time regex
Error message
invalid ctest time regex
What it means
This is a panic from `.expect("invalid ctest time regex")` on `Regex::new` inside the TIME_RE LazyLock static at src/cmds/system/ctest_cmd.rs:46. TIME_RE extracts the value from ctest's `Total Test time (real) = N sec` line. The panic fires when the pattern literal fails regex compilation; since rtk's regex statics are LazyLock, the crash occurs on the first ctest filtering run that reaches the time-extraction code path.
Source
Thrown at src/cmds/system/ctest_cmd.rs:46
.expect("invalid ctest result regex")
});
static RESULT_PREFIX_RE: LazyLock<Regex> = LazyLock::new(|| {
Regex::new(r"^\s*(?:\d+/\d+\s+)?Test\s+#\d+:")
.expect("invalid ctest result prefix regex")
});
static RESULT_TERMINATOR_RE: LazyLock<Regex> = LazyLock::new(|| {
Regex::new(r"[\d.]+\s+sec\s*$").expect("invalid ctest result terminator regex")
});
static START_RE: LazyLock<Regex> = LazyLock::new(|| {
Regex::new(r"^\s*Start\s+(\d+):\s*(.*?)\s*$").expect("invalid ctest start regex")
});
static SUMMARY_RE: LazyLock<Regex> = LazyLock::new(|| {
Regex::new(r"^\s*\d+%\s+tests passed,\s+(\d+)\s+tests failed out of\s+(\d+)")
.expect("invalid ctest summary regex")
});
static TIME_RE: LazyLock<Regex> = LazyLock::new(|| {
Regex::new(r"^\s*Total Test time \(real\)\s+=\s+([\d.]+)\s+sec")
.expect("invalid ctest time regex")
});
#[derive(Debug, Clone)]
struct TestCase {
number: u32,
name: String,
status: String,
reason: Option<String>,
duration: f64,
line_index: usize,
counter_total: Option<u32>,
}
#[derive(Debug)]
struct ParsedTests {
tests: Vec<TestCase>,
result_lines: Vec<usize>,
run_total: Option<u32>,View on GitHub (pinned to 36788f6bd4)
Solutions
- Check the TIME_RE literal at src/cmds/system/ctest_cmd.rs:46-47; ensure literal parentheses are escaped as `\(` and `\)`
- Fix the specific regex parse error and validate the pattern on regex101 (Rust flavor)
- Restore the known-good pattern: r"^\s*Total Test time \(real\)\s+=\s+([\d.]+)\s+sec"
- Run cargo test for the ctest module and cargo clippy --all-targets before committing
Example fix
// before (unescaped parens make `)` an unmatched group close after other edits)
Regex::new(r"^\s*Total Test time (real)\s+=\s+([\d.]+\s+sec")
.expect("invalid ctest time regex")
// after
Regex::new(r"^\s*Total Test time \(real\)\s+=\s+([\d.]+)\s+sec")
.expect("invalid ctest time regex") Defensive patterns
Strategy: validation
Validate before calling
fn assert_time_regex_valid() {
assert!(regex::Regex::new(r"^\s*Total Test time \(real\)\s+=\s+([\d.]+)\s+sec").is_ok());
} Prevention
- Remember literal parens in output text must be escaped `\(` `\)` in regex
- Never strip escapes from regex literals without re-running the fixture tests
- Add a Regex::new(...).is_ok() unit test for TIME_RE and all sibling statics
- Run the pre-commit gate (cargo fmt && clippy && test) after any regex edit
When it happens
Trigger: First use of TIME_RE after its pattern `^\s*Total Test time \(real\)\s+=\s+([\d.]+)\s+sec` was corrupted — most often an unescaped `(` or `)` in the literal (the parens around `real` must stay escaped in regex), producing a capture-group or repetition error.
Common situations: Someone 'cleans up' the escaped parens `\(real\)` to `(real)`, unintentionally creating a valid-but-unintended group (or, if combined with other edits, an invalid one); backslash loss when the string stops being a raw string; merge conflicts in the statics block.
Related errors
- invalid ctest result prefix regex
- invalid ctest result terminator regex
- invalid ctest start regex
- invalid ctest summary regex
AI-assisted analysis of rtk-ai/rtk@36788f6bd4 (2026-09-03).
Data as JSON: /api/errors/b4eee058f3c330fd.
Report an issue: GitHub.