{"record":{"id":"35d62c526bbbf92f","repo":"Hmbown/CodeWhale","slug":"bing-title-regex-pattern-is-valid","errorCode":null,"errorMessage":"bing title regex pattern is valid","messagePattern":"bing title regex pattern is valid","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/tui/src/tools/web/scrape.rs","lineNumber":61,"sourceCode":"        .expect(\"snippet regex pattern is valid\")\n    })\n}\n\nfn get_tag_re() -> &'static Regex {\n    TAG_RE.get_or_init(|| Regex::new(r\"<[^>]+>\").expect(\"tag regex pattern is valid\"))\n}\n\nfn get_bing_result_re() -> &'static Regex {\n    BING_RESULT_RE.get_or_init(|| {\n        Regex::new(r#\"(?is)<li[^>]*class=\\\"[^\\\"]*\\bb_algo\\b[^\\\"]*\\\"[^>]*>(.*?)</li>\"#)\n            .expect(\"bing result regex pattern is valid\")\n    })\n}\n\nfn get_bing_title_re() -> &'static Regex {\n    BING_TITLE_RE.get_or_init(|| {\n        Regex::new(r#\"(?is)<h2[^>]*>.*?<a[^>]*href=\\\"([^\\\"]+)\\\"[^>]*>(.*?)</a>\"#)\n            .expect(\"bing title regex pattern is valid\")\n    })\n}\n\nfn get_bing_snippet_re() -> &'static Regex {\n    BING_SNIPPET_RE.get_or_init(|| {\n        Regex::new(r#\"(?is)<div[^>]*class=\\\"[^\\\"]*\\bb_caption\\b[^\\\"]*\\\"[^>]*>.*?<p[^>]*>(.*?)</p>\"#)\n            .expect(\"bing snippet regex pattern is valid\")\n    })\n}\n\n/// Parse DuckDuckGo HTML SERP results. Known spam-domain hits are omitted.\npub fn parse_duckduckgo_results(html: &str, max_results: usize) -> Vec<ScrapedSearchResult> {\n    let title_re = get_title_re();\n    let snippet_re = get_snippet_re();\n    let snippets: Vec<String> = snippet_re\n        .captures_iter(html)\n        .filter_map(|cap| cap.get(1).or_else(|| cap.get(2)))\n        .map(|m| normalize_text(m.as_str()))","sourceCodeStart":43,"sourceCodeEnd":79,"githubUrl":"https://github.com/Hmbown/CodeWhale/blob/0c42157ee52f9d55af2b506d71b46249910f77d3/crates/tui/src/tools/web/scrape.rs#L43-L79","documentation":"Panic compiling the Bing result-title pattern `(?is)<h2[^>]*>.*?<a[^>]*href=\"([^\"]+)\"[^>]*>(.*?)</a>` in `BING_TITLE_RE.get_or_init`. It depends on two capture groups (URL and anchor text) that downstream code indexes; an edit that removes or reorders groups compiles fine but breaks extraction, while an edit that breaks group/quote balance makes `Regex::new` fail and trips the expect.","triggerScenarios":"Editing the Bing title literal and leaving an unbalanced group or malformed quote escape; the first Bing scrape after that build panics inside the getter.","commonSituations":"Coping with Bing wrapping titles in extra spans; pasting a pattern where a `\"` inside the raw-string/regex double-escaping got mangled.","solutions":["Fix the literal, keeping exactly two capture groups in the order URL-then-anchor.","Pin the group layout in a unit test (`captures_len()`), not just compilation.","Run the Bing scrape tests after the edit."],"exampleFix":"// before\nRegex::new(r#\"(?is)<h2[^>]*>.*?<a[^>]*href=\\\"([^\\\"]+)\\\"[^>]*>(.*?)</a>\"#)\n    .expect(\"bing title regex pattern is valid\")\n\n// after: pin both compilation and capture-group layout\n#[test]\nfn bing_title_pattern_shape() {\n    let re = get_bing_title_re();\n    assert_eq!(re.captures_len() - 1, 2);\n}","handlingStrategy":"validation","validationCode":"#[test]\nfn bing_title_pattern_shape() {\n    let re = get_bing_title_re();\n    assert_eq!(re.captures_len() - 1, 2); // URL group, then anchor-text group\n}","typeGuard":null,"tryCatchPattern":"let titles = std::panic::catch_unwind(|| extract_bing_titles(&html))\n    .unwrap_or_default();","preventionTips":["Preserve capture-group order when editing; downstream code indexes groups positionally.","Pair every pattern edit with a fixture test, not just a compile check."],"tags":["rust","regex","bing","html-scraping","panic","expect"],"backgroundTag":"invalid-regex-pattern","analyzedSha":"0c42157ee52f9d55af2b506d71b46249910f77d3","analyzedAt":"2026-08-20T21:50:45.477Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}