rtk-ai/rtk · critical
invalid ctest start regex
Error message
invalid ctest start regex
What it means
This is a panic from `.expect("invalid ctest start regex")` on `Regex::new` inside the START_RE LazyLock static at src/cmds/system/ctest_cmd.rs:38. START_RE matches `Start N: <test name>` lines emitted by ctest; an invalid pattern makes rtk panic on first use instead of silently producing wrong output. It is a programmer error in the pattern literal, not a runtime/input problem.
Source
Thrown at src/cmds/system/ctest_cmd.rs:38
// so this list deviates below `CAP_LIST`; the single-line skipped and raw-trailer
// lists keep the full cap.
const MAX_FAILED_BLOCK_ENTRIES: usize = truncate::reduced(CAP_LIST, 5);
static TEST_RE: LazyLock<Regex> = LazyLock::new(|| {
Regex::new(
r"(?s)^\s*(?:\d+/(\d+)\s+)?Test\s+#(\d+):\s+(.+?)\s+\.{2,}\s*(?:\*{3})?\s*(.+?)\s+([\d.]+)\s+sec\s*$",
)
.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,View on GitHub (pinned to 36788f6bd4)
Solutions
- Open src/cmds/system/ctest_cmd.rs around line 38 and fix the START_RE pattern syntax
- Balance-check parentheses and escapes in the literal; validate on regex101 (Rust flavor)
- Restore the known-good pattern: r"^\s*Start\s+(\d+):\s*(.*?)\s*$"
- Add a #[test] that asserts Regex::new(PATTERN).is_ok() for each ctest static to catch this at CI time
Example fix
// before (unclosed capture group)
Regex::new(r"^\s*Start\s+(\d+:\s*(.*?)\s*$").expect("invalid ctest start regex")
// after
Regex::new(r"^\s*Start\s+(\d+):\s*(.*?)\s*$").expect("invalid ctest start regex") Defensive patterns
Strategy: validation
Validate before calling
fn assert_start_regex_valid() {
assert!(regex::Regex::new(r"^\s*Start\s+(\d+):\s*(.*?)\s*$").is_ok());
} Prevention
- Count opening/closing parens whenever adding or renaming capture groups
- Use a regex lint/clippy pass or editor plugin that highlights unbalanced groups
- Snapshot-test START_RE against real `ctest -V` start lines
- Keep each regex static on its own lines so diffs isolate pattern changes
When it happens
Trigger: The first time the ctest filter processes output after START_RE's pattern `^\s*Start\s+(\d+):\s*(.*?)\s*$` was corrupted — e.g. an unclosed capture group `(`, a repetition operator with nothing to repeat (`*?` at pattern start), or an invalid unicode escape.
Common situations: Renaming the capture group or adding a new group and leaving an unbalanced paren, converting the raw string to a normal string so `\s` becomes an unknown escape, or manual conflict resolution dropping one `)` from the line.
Related errors
- invalid ctest result prefix regex
- invalid ctest result terminator regex
- invalid ctest summary regex
- invalid ctest time regex
AI-assisted analysis of rtk-ai/rtk@36788f6bd4 (2026-09-03).
Data as JSON: /api/errors/f4e2ed222493cfb2.
Report an issue: GitHub.