{"record":{"id":"abb00724d713a291","repo":"can1357/oh-my-pi","slug":"err-to-string-invalid-exclude-glob-pattern","errorCode":null,"errorMessage":"err.to_string() (invalid exclude glob pattern)","messagePattern":"err\\.to_string\\(\\) \\(invalid exclude glob pattern\\)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/pi-builtins/src/fd.rs","lineNumber":1250,"sourceCode":"\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)))\n}\n\nfn build_type_filter(types: &[String]) -> io::Result<TypeFilter> {\n\tlet mut filter = TypeFilter::default();\n\tfor value in types {\n\t\tmatch value.as_str() {\n\t\t\t\"f\" | \"file\" => filter.regular = true,\n\t\t\t\"d\" | \"dir\" | \"directory\" => filter.directory = true,\n\t\t\t\"l\" | \"symlink\" => filter.symlink = true,\n\t\t\t\"s\" | \"socket\" => filter.socket = true,\n\t\t\t\"p\" | \"pipe\" => filter.pipe = true,\n\t\t\t\"b\" | \"block-device\" => filter.block = true,\n\t\t\t\"c\" | \"char-device\" => filter.character = true,\n\t\t\t\"x\" | \"executable\" => filter.executable = true,\n\t\t\t\"e\" | \"empty\" => filter.empty = true,","sourceCodeStart":1232,"sourceCodeEnd":1268,"githubUrl":"https://github.com/can1357/oh-my-pi/blob/969062200754ea02cfac922e5ebb8c608c079e15/crates/pi-builtins/src/fd.rs#L1232-L1268","documentation":"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).","triggerScenarios":"`fd pattern --exclude '['` or `--exclude 'a{b'` — unbalanced character classes/braces or dangling escapes in exclusion globs.","commonSituations":"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.","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"],"exampleFix":"// before\nfd . --exclude 'node_modules('  // invalid paren\n// after\nfd . --exclude '**/node_modules/**'","handlingStrategy":"validation","validationCode":"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(()) }","typeGuard":"fn is_exclude_glob_error(msg: &str) -> bool { msg.contains(\"error parsing glob\") }","tryCatchPattern":"let excludes = build_excludes(&patterns).map_err(|e| format!(\"fd: bad --exclude: {}\", e))?;","preventionTips":["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"],"tags":["glob","validation","fd","rust"],"backgroundTag":"invalid-glob-pattern","analyzedSha":"969062200754ea02cfac922e5ebb8c608c079e15","analyzedAt":"2026-08-31T10:29:35.737Z","schemaVersion":2},"datasetVersion":"2026-08-31T14:17:45.589Z"}