can1357/oh-my-pi · error
err.to_string() (invalid exclude glob pattern)
Error message
err.to_string() (invalid exclude glob pattern)
What it means
fd compiles each --exclude pattern with GlobBuilder (literal_separator(true)); invalid exclude globs fail compilation and are converted to InvalidInput with err.to_string(). Note excludes always use glob syntax and are case-sensitive here (no case_insensitive flag is passed).
Source
Thrown at crates/pi-builtins/src/fd.rs:1250
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)))
}
fn build_type_filter(types: &[String]) -> io::Result<TypeFilter> {
let mut filter = TypeFilter::default();
for value in types {
match value.as_str() {
"f" | "file" => filter.regular = true,
"d" | "dir" | "directory" => filter.directory = true,
"l" | "symlink" => filter.symlink = true,
"s" | "socket" => filter.socket = true,
"p" | "pipe" => filter.pipe = true,
"b" | "block-device" => filter.block = true,
"c" | "char-device" => filter.character = true,
"x" | "executable" => filter.executable = true,
"e" | "empty" => filter.empty = true,View on GitHub (pinned to 9690622007)
Solutions
- Fix the exclude glob syntax (balance []/{}, escape literal specials)
- Quote/escape patterns loaded from config; filter invalid entries before passing them
- Use --fixed-strings on the include side and translate exclusions to valid globs (e.g. `**/name`)
- Validate patterns with a glob library before generating the command
Example fix
// before
fd . --exclude 'node_modules(' // invalid paren
// after
fd . --exclude '**/node_modules/**' Defensive patterns
Strategy: validation
Validate before calling
use glob::Pattern;fn validate_excludes(pats: &[String]) -> Result<(), String> { for p in pats { Pattern::new(p).map_err(|e| format!("exclude '{}': {}", p, e))?; } Ok(()) } Type guard
fn is_exclude_glob_error(msg: &str) -> bool { msg.contains("error parsing glob") } Try / catch
let excludes = build_excludes(&patterns).map_err(|e| format!("fd: bad --exclude: {}", e))?; Prevention
- Escape [ and { when excluding files whose names contain them literally
- Validate config-sourced exclude lists at load time, not at fd invocation
- Remember excludes are globs (like .gitignore), not regexes or plain substrings
When it happens
Trigger: `fd pattern --exclude '['` or `--exclude 'a{b'` — unbalanced character classes/braces or dangling escapes in exclusion globs.
Common situations: Exclude lists generated from config files where some entries aren't valid globs, unescaped brackets in patterns meant to match literal filenames (e.g. `foo[1]`), or Windows-style backslash paths used as globs.
Related errors
- err.to_string() (invalid glob pattern)
- err.to_string() (invalid regex pattern)
- --list-details, --exec, and --exec-batch are not supported b
- positional paths cannot be combined with --search-path
- invalid {} argument: {}
AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31).
Data as JSON: /api/errors/abb00724d713a291.
Report an issue: GitHub.