zed-industries/zed · error · anyhow::Error
Invalid glob: {err}
Error message
Invalid glob: {err} What it means
The path-search tool could not compile the glob: `PathMatcher::new` returned Err for the pattern (after the special case mapping an empty glob to '*'). The message is the matcher parser's own error describing the syntax problem, so the glob never runs against the worktree.
Source
Thrown at crates/agent/src/tools/find_path_tool.rs:192
offset: input.offset,
current_matches_page: paginated_matches.to_vec(),
all_matches_len: matches.len(),
})
})
}
}
fn search_paths(glob: &str, project: Entity<Project>, cx: &mut App) -> Task<Result<Vec<PathBuf>>> {
let path_style = project.read(cx).path_style(cx);
let path_matcher = match PathMatcher::new(
[
// Sometimes models try to search for "". In this case, return all paths in the project.
if glob.is_empty() { "*" } else { glob },
],
path_style,
) {
Ok(matcher) => matcher,
Err(err) => return Task::ready(Err(anyhow!("Invalid glob: {err}"))),
};
let snapshots: Vec<_> = project
.read(cx)
.worktrees(cx)
.map(|worktree| worktree.read(cx).snapshot())
.collect();
cx.background_spawn(async move {
let mut results = Vec::new();
for snapshot in snapshots {
for entry in snapshot.entries(false, 0) {
if path_matcher.is_match(&snapshot.root_name().join(&entry.path)) {
results.push(snapshot.absolutize(&entry.path));
}
}
}
Ok(results)View on GitHub (pinned to bc538def45)
Solutions
- Use simple, well-formed wildcards: `*.rs`, `src/**/*.ts`, `foo?/bar`.
- Validate the pattern with `PathMatcher::new` before running the tool and surface the parser error to the caller.
- If regex semantics are needed, use a regex-capable tool, not the glob tool.
- Fix unbalanced `[`/`{` and remove regex constructs from the pattern.
Example fix
# before find_path(pattern=".*\\.rs$") # regex — Invalid glob find_path(pattern="[a-z") # unbalanced bracket # after find_path(pattern="**/*.rs")
Defensive patterns
Strategy: validation
Validate before calling
let effective_glob = if glob.is_empty() { "*" } else { glob };
if let Err(err) = PathMatcher::new([effective_glob], path_style) {
anyhow::bail!("invalid glob {glob:?}: {err}");
} Type guard
fn is_valid_glob(glob: &str, path_style: PathStyle) -> bool {
let effective = if glob.is_empty() { "*" } else { glob };
PathMatcher::new([effective], path_style).is_ok()
} Prevention
- Document in tool descriptions that patterns are globs, not regex ('**/*.rs', not '.*\\.rs').
- Lint user- or model-supplied patterns through PathMatcher before dispatch.
- Remember the empty glob means 'match all paths' — avoid accidental full-project scans.
When it happens
Trigger: Globs with unbalanced brackets or braces, stray metacharacters, or invalid character classes — typically model-authored patterns like `[a-z`, `{foo`, or regex-style inputs such as `.*\.rs` passed to a glob matcher.
Common situations: LLM-generated patterns confusing regex and glob syntax; Windows/Unix separator confusion; nested brace expansions the matcher does not support.
Related errors
- {input_path} is not a directory.
- {error_message}
- Path not found: {}
- Unexpected response structure: ${JSON.stringify(data)}
- unknown benchmark '{benchmark_id}' (valid: {valid})
AI-assisted analysis of zed-industries/zed@bc538def45 (2026-08-16).
Data as JSON: /api/errors/b6f6c509df400a53.
Report an issue: GitHub.