{"record":{"id":"b4eee058f3c330fd","repo":"rtk-ai/rtk","slug":"invalid-ctest-time-regex","errorCode":null,"errorMessage":"invalid ctest time regex","messagePattern":"invalid ctest time regex","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"src/cmds/system/ctest_cmd.rs","lineNumber":46,"sourceCode":"    .expect(\"invalid ctest result regex\")\n});\nstatic RESULT_PREFIX_RE: LazyLock<Regex> = LazyLock::new(|| {\n    Regex::new(r\"^\\s*(?:\\d+/\\d+\\s+)?Test\\s+#\\d+:\")\n        .expect(\"invalid ctest result prefix regex\")\n});\nstatic RESULT_TERMINATOR_RE: LazyLock<Regex> = LazyLock::new(|| {\n    Regex::new(r\"[\\d.]+\\s+sec\\s*$\").expect(\"invalid ctest result terminator regex\")\n});\nstatic START_RE: LazyLock<Regex> = LazyLock::new(|| {\n    Regex::new(r\"^\\s*Start\\s+(\\d+):\\s*(.*?)\\s*$\").expect(\"invalid ctest start regex\")\n});\nstatic SUMMARY_RE: LazyLock<Regex> = LazyLock::new(|| {\n    Regex::new(r\"^\\s*\\d+%\\s+tests passed,\\s+(\\d+)\\s+tests failed out of\\s+(\\d+)\")\n        .expect(\"invalid ctest summary regex\")\n});\nstatic TIME_RE: LazyLock<Regex> = LazyLock::new(|| {\n    Regex::new(r\"^\\s*Total Test time \\(real\\)\\s+=\\s+([\\d.]+)\\s+sec\")\n        .expect(\"invalid ctest time regex\")\n});\n\n#[derive(Debug, Clone)]\nstruct TestCase {\n    number: u32,\n    name: String,\n    status: String,\n    reason: Option<String>,\n    duration: f64,\n    line_index: usize,\n    counter_total: Option<u32>,\n}\n\n#[derive(Debug)]\nstruct ParsedTests {\n    tests: Vec<TestCase>,\n    result_lines: Vec<usize>,\n    run_total: Option<u32>,","sourceCodeStart":28,"sourceCodeEnd":64,"githubUrl":"https://github.com/rtk-ai/rtk/blob/36788f6bd4932037caac5cbb1d15d6e2fb9f33da/src/cmds/system/ctest_cmd.rs#L28-L64","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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"],"exampleFix":"// before (unescaped parens make `)` an unmatched group close after other edits)\nRegex::new(r\"^\\s*Total Test time (real)\\s+=\\s+([\\d.]+\\s+sec\")\n    .expect(\"invalid ctest time regex\")\n// after\nRegex::new(r\"^\\s*Total Test time \\(real\\)\\s+=\\s+([\\d.]+)\\s+sec\")\n    .expect(\"invalid ctest time regex\")","handlingStrategy":"validation","validationCode":"fn assert_time_regex_valid() {\n    assert!(regex::Regex::new(r\"^\\s*Total Test time \\(real\\)\\s+=\\s+([\\d.]+)\\s+sec\").is_ok());\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["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"],"tags":["regex","panic","escaping","ctest"],"backgroundTag":"invalid-regex-pattern","analyzedSha":"36788f6bd4932037caac5cbb1d15d6e2fb9f33da","analyzedAt":"2026-09-03T16:33:57.738Z","contentChangedAt":"2026-09-03T16:33:57.738Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}