{"record":{"id":"8c10d03c0b0ed6ba","repo":"can1357/oh-my-pi","slug":"err-to-string-invalid-regex-pattern","errorCode":null,"errorMessage":"err.to_string() (invalid regex pattern)","messagePattern":"err\\.to_string\\(\\) \\(invalid regex pattern\\)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/pi-builtins/src/fd.rs","lineNumber":1235,"sourceCode":"\t\treturn Ok(SearchMatcher::Glob(matchers));\n\t}\n\tif cli.fixed_strings {\n\t\tlet patterns = if case_insensitive {\n\t\t\tpatterns\n\t\t\t\t.into_iter()\n\t\t\t\t.map(|pattern| pattern.to_lowercase())\n\t\t\t\t.collect()\n\t\t} else {\n\t\t\tpatterns\n\t\t};\n\t\treturn Ok(SearchMatcher::Fixed { patterns, case_insensitive });\n\t}\n\tlet mut regexes = Vec::with_capacity(patterns.len());\n\tfor pattern in patterns {\n\t\tlet regex = RegexBuilder::new(&pattern)\n\t\t\t.case_insensitive(case_insensitive)\n\t\t\t.build()\n\t\t\t.map_err(|err| io::Error::new(io::ErrorKind::InvalidInput, err.to_string()))?;\n\t\tregexes.push(regex);\n\t}\n\tOk(SearchMatcher::Regex(regexes))\n}\n\nfn build_excludes(patterns: &[String]) -> io::Result<Excludes> {\n\tif patterns.is_empty() {\n\t\treturn Ok(Excludes::empty());\n\t}\n\tlet mut matchers = Vec::with_capacity(patterns.len());\n\tfor pattern in patterns {\n\t\tlet glob = GlobBuilder::new(pattern)\n\t\t\t.literal_separator(true)\n\t\t\t.build()\n\t\t\t.map_err(|err| io::Error::new(io::ErrorKind::InvalidInput, err.to_string()))?;\n\t\tmatchers.push(glob.compile_matcher());\n\t}\n\tOk(Excludes(Arc::new(matchers)))","sourceCodeStart":1217,"sourceCodeEnd":1253,"githubUrl":"https://github.com/can1357/oh-my-pi/blob/969062200754ea02cfac922e5ebb8c608c079e15/crates/pi-builtins/src/fd.rs#L1217-L1253","documentation":"fd compiles include regex patterns with RegexBuilder (case-insensitivity optional); an invalid regular expression produces a regex::Error, surfaced as InvalidInput with err.to_string(). Compilation happens up front, before any filesystem traversal.","triggerScenarios":"`fd '(foo'`, `fd '*x'`, `fd 'a{2,1}'` — unclosed groups, regex metacharacters used as literals, or invalid repetition ranges.","commonSituations":"Users confusing glob syntax with regex (fnmatch `*` vs regex `.*`), dynamically built patterns from variables, or patterns copied from grep -E with unsupported syntax.","solutions":["Fix the regex: close all groups, use .* instead of * for globs, and correct {m,n} ranges","Escape literal metacharacters (. ( ) [ ] { } * + ? ^ $ | \\) with backslash or use --fixed-strings","Validate the pattern with a regex playground or RegexBuilder::new(p).build() before scripting it"],"exampleFix":"// before\nfd 'file(1)'   // unescaped parens\n// after\nfd 'file\\(1\\)'   // or: fd --fixed-strings 'file(1)'","handlingStrategy":"validation","validationCode":"function validRegex(p) { try { new RegExp(p); return true; } catch { return false; } }patterns.forEach(p => { if (!validRegex(p)) throw new Error(`invalid regex: ${p}`); });","typeGuard":"fn is_regex_error(msg: &str) -> bool { msg.contains(\"regex parse error\") || msg.contains(\"unrecognized escape\") }","tryCatchPattern":"let regexes = patterns.iter().map(|p| RegexBuilder::new(p).build()).collect::<Result<Vec<_>, _>>().map_err(|e| format!(\"bad regex: {}\", e))?;","preventionTips":["Escape regex metacharacters when interpolating user input into patterns","Use --fixed-strings for literal searches instead of escaping by hand","Test dynamic patterns with RegexBuilder::new(p).build() in unit tests"],"tags":["regex","validation","fd","rust"],"backgroundTag":"invalid-regex-pattern","analyzedSha":"969062200754ea02cfac922e5ebb8c608c079e15","analyzedAt":"2026-08-31T10:29:35.737Z","schemaVersion":2},"datasetVersion":"2026-08-31T14:17:45.589Z"}