{"record":{"id":"3bb6e388c2aca8bc","repo":"can1357/oh-my-pi","slug":"err-to-string-invalid-glob-pattern","errorCode":null,"errorMessage":"err.to_string() (invalid glob pattern)","messagePattern":"err\\.to_string\\(\\) \\(invalid glob pattern\\)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/pi-builtins/src/fd.rs","lineNumber":1214,"sourceCode":"\t}\n\tlet case_insensitive = if cli.ignore_case {\n\t\ttrue\n\t} else if cli.case_sensitive {\n\t\tfalse\n\t} else {\n\t\t!patterns\n\t\t\t.iter()\n\t\t\t.any(|pattern| pattern.chars().any(char::is_uppercase))\n\t};\n\n\tif cli.glob {\n\t\tlet mut matchers = Vec::with_capacity(patterns.len());\n\t\tfor pattern in patterns {\n\t\t\tlet glob = GlobBuilder::new(&pattern)\n\t\t\t\t.literal_separator(true)\n\t\t\t\t.case_insensitive(case_insensitive)\n\t\t\t\t.build()\n\t\t\t\t.map_err(|err| io::Error::new(io::ErrorKind::InvalidInput, err.to_string()))?;\n\t\t\tmatchers.push(glob.compile_matcher());\n\t\t}\n\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)","sourceCodeStart":1196,"sourceCodeEnd":1232,"githubUrl":"https://github.com/can1357/oh-my-pi/blob/969062200754ea02cfac922e5ebb8c608c079e15/crates/pi-builtins/src/fd.rs#L1196-L1232","documentation":"fd compiles each include glob pattern with the glob crate's GlobBuilder (literal_separator enabled, optional case-insensitivity); a syntactically invalid pattern yields a PatternError, which fd converts to InvalidInput with the parser's message via err.to_string().","triggerScenarios":"`fd --glob '['` or `--glob 'a{b'` — unbalanced brackets/braces, dangling escape like `foo\\`, or an empty/invalid alternation in the glob.","commonSituations":"Hand-written globs with unescaped `[` (e.g. matching literal brackets in filenames), patterns built by string concatenation in scripts, or patterns quoted incorrectly so the shell strips characters.","solutions":["Fix the glob syntax: balance [] and {}, and escape literal specials with backslash","Quote the pattern in the shell so brackets/braces survive (single quotes are safest)","Validate the pattern by compiling it with a glob tester before embedding in scripts","If you meant a plain substring, use --fixed-strings instead of --glob"],"exampleFix":"// before\nfd --glob 'src/[[:num]]'    // malformed class\n// after\nfd --glob 'src/[0-9]*'","handlingStrategy":"validation","validationCode":"use glob::Pattern;fn valid_glob(p: &str) -> bool { Pattern::new(p).is_ok() }let bad: Vec<_> = patterns.iter().filter(|p| !valid_glob(p)).collect();if !bad.is_empty() { return Err(format!(\"invalid glob(s): {:?}\", bad)); }","typeGuard":"fn is_glob_error(msg: &str) -> bool { msg.contains(\"error parsing glob\") || msg.contains(\"PatternError\") }","tryCatchPattern":"let matchers: Vec<_> = patterns.iter().map(|p| GlobBuilder::new(p).literal_separator(true).build()).collect::<Result<_, _>>().map_err(|e| format!(\"bad glob: {}\", e))?;","preventionTips":["Single-quote glob patterns in shell to protect [] and {}","Lint script-generated patterns with Pattern::new before invoking fd","Prefer --fixed-strings when you don't need wildcards"],"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"}