{"record":{"id":"808ced0343a5dfb5","repo":"rtk-ai/rtk","slug":"invalid-ctest-result-prefix-regex","errorCode":null,"errorMessage":"invalid ctest result prefix regex","messagePattern":"invalid ctest result prefix regex","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"src/cmds/system/ctest_cmd.rs","lineNumber":32,"sourceCode":"const MAX_SLOWEST: usize = 3;\nconst MAX_FAILURE_LINES: usize = CAP_WARNINGS;\nconst MAX_FAILURE_HEAD_LINES: usize = 2;\nconst MAX_FAILED_LIST_LINES: usize = CAP_LIST;\nconst MAX_DETECT_PREAMBLE_LINES: usize = 4;\n// Failure entries carry a header plus up to `MAX_FAILURE_LINES` detail lines each,\n// so this list deviates below `CAP_LIST`; the single-line skipped and raw-trailer\n// lists keep the full cap.\nconst MAX_FAILED_BLOCK_ENTRIES: usize = truncate::reduced(CAP_LIST, 5);\n\nstatic TEST_RE: LazyLock<Regex> = LazyLock::new(|| {\n    Regex::new(\n        r\"(?s)^\\s*(?:\\d+/(\\d+)\\s+)?Test\\s+#(\\d+):\\s+(.+?)\\s+\\.{2,}\\s*(?:\\*{3})?\\s*(.+?)\\s+([\\d.]+)\\s+sec\\s*$\",\n    )\n    .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 {","sourceCodeStart":14,"sourceCodeEnd":50,"githubUrl":"https://github.com/rtk-ai/rtk/blob/36788f6bd4932037caac5cbb1d15d6e2fb9f33da/src/cmds/system/ctest_cmd.rs#L14-L50","documentation":"This is a panic from `.expect(\"invalid ctest result prefix regex\")` on a `Regex::new` call inside a `LazyLock<Regex>` static in src/cmds/system/ctest_cmd.rs:32. The `regex` crate returns an Err when a pattern fails to parse, and rtk's convention is to crash at first use rather than run with broken filtering. It means the RESULT_PREFIX_RE pattern string is syntactically invalid regex.","triggerScenarios":"The static RESULT_PREFIX_RE is lazily initialized the first time the ctest filter uses it; the panic fires only if the literal pattern `^\\s*(?:\\d+/\\d+\\s+)?Test\\s+#\\d+:` fails to compile — i.e. after a source edit that corrupts the pattern (unbalanced parentheses/groups, bad escape like `\\q`, dangling `*`, truncated string literal).","commonSituations":"Hand-editing the regex while adding support for new ctest output shapes (e.g. changing `(?:\\d+/\\d+\\s+)` and dropping the `?` or a paren), copy-paste mangling backslashes between raw and non-raw strings, or merging branches that both touched the static.","solutions":["Inspect the RESULT_PREFIX_RE pattern literal at src/cmds/system/ctest_cmd.rs:32-34 and fix the regex syntax error reported by Regex::new","Verify the pattern standalone (e.g. `cargo run` with a small Regex::new test, or regex101 with Rust flavor) before re-committing","Restore the known-good pattern: r\"^\\s*(?:\\d+/\\d+\\s+)?Test\\s+#\\d+:\"","Run `cargo test ctest` to confirm the filter initializes and matches real ctest output lines"],"exampleFix":"// before (missing closing paren on the non-capturing group)\nRegex::new(r\"^\\s*(?:\\d+/\\d+\\s+?Test\\s+#\\d+:\")\n    .expect(\"invalid ctest result prefix regex\")\n// after\nRegex::new(r\"^\\s*(?:\\d+/\\d+\\s+)?Test\\s+#\\d+:\")\n    .expect(\"invalid ctest result prefix regex\")","handlingStrategy":"validation","validationCode":"// Run in CI before depending on the filter; cheap Regex::new check\nfn assert_ctest_regexes_valid() {\n    assert!(regex::Regex::new(r\"^\\s*(?:\\d+/\\d+\\s+)?Test\\s+#\\d+:\").is_ok());\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Keep regex patterns as raw strings (r\"...\") so backslashes never need double-escaping","Add a unit test that Regex::new(...).is_ok() for every LazyLock regex static in ctest_cmd.rs","Validate edited patterns on regex101 with the Rust flavor before committing","Never hand-edit regexes during merge conflict resolution — take one side and re-verify"],"tags":["regex","panic","compile-time-pattern","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"}