can1357/oh-my-pi · error

err.to_string() (invalid regex pattern)

Error message

err.to_string() (invalid regex pattern)

What it means

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.

Source

Thrown at crates/pi-builtins/src/fd.rs:1235

		return Ok(SearchMatcher::Glob(matchers));
	}
	if cli.fixed_strings {
		let patterns = if case_insensitive {
			patterns
				.into_iter()
				.map(|pattern| pattern.to_lowercase())
				.collect()
		} else {
			patterns
		};
		return Ok(SearchMatcher::Fixed { patterns, case_insensitive });
	}
	let mut regexes = Vec::with_capacity(patterns.len());
	for pattern in patterns {
		let regex = RegexBuilder::new(&pattern)
			.case_insensitive(case_insensitive)
			.build()
			.map_err(|err| io::Error::new(io::ErrorKind::InvalidInput, err.to_string()))?;
		regexes.push(regex);
	}
	Ok(SearchMatcher::Regex(regexes))
}

fn build_excludes(patterns: &[String]) -> io::Result<Excludes> {
	if patterns.is_empty() {
		return Ok(Excludes::empty());
	}
	let mut matchers = Vec::with_capacity(patterns.len());
	for pattern in patterns {
		let glob = GlobBuilder::new(pattern)
			.literal_separator(true)
			.build()
			.map_err(|err| io::Error::new(io::ErrorKind::InvalidInput, err.to_string()))?;
		matchers.push(glob.compile_matcher());
	}
	Ok(Excludes(Arc::new(matchers)))

View on GitHub (pinned to 9690622007)

Solutions

  1. Fix the regex: close all groups, use .* instead of * for globs, and correct {m,n} ranges
  2. Escape literal metacharacters (. ( ) [ ] { } * + ? ^ $ | \) with backslash or use --fixed-strings
  3. Validate the pattern with a regex playground or RegexBuilder::new(p).build() before scripting it

Example fix

// before
fd 'file(1)'   // unescaped parens
// after
fd 'file\(1\)'   // or: fd --fixed-strings 'file(1)'
Defensive patterns

Strategy: validation

Validate before calling

function validRegex(p) { try { new RegExp(p); return true; } catch { return false; } }patterns.forEach(p => { if (!validRegex(p)) throw new Error(`invalid regex: ${p}`); });

Type guard

fn is_regex_error(msg: &str) -> bool { msg.contains("regex parse error") || msg.contains("unrecognized escape") }

Try / catch

let regexes = patterns.iter().map(|p| RegexBuilder::new(p).build()).collect::<Result<Vec<_>, _>>().map_err(|e| format!("bad regex: {}", e))?;

Prevention

When it happens

Trigger: `fd '(foo'`, `fd '*x'`, `fd 'a{2,1}'` — unclosed groups, regex metacharacters used as literals, or invalid repetition ranges.

Common situations: Users confusing glob syntax with regex (fnmatch `*` vs regex `.*`), dynamically built patterns from variables, or patterns copied from grep -E with unsupported syntax.

Related errors


AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31). Data as JSON: /api/errors/8c10d03c0b0ed6ba. Report an issue: GitHub.