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

  1. Use simple, well-formed wildcards: `*.rs`, `src/**/*.ts`, `foo?/bar`.
  2. Validate the pattern with `PathMatcher::new` before running the tool and surface the parser error to the caller.
  3. If regex semantics are needed, use a regex-capable tool, not the glob tool.
  4. 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

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


AI-assisted analysis of zed-industries/zed@bc538def45 (2026-08-16). Data as JSON: /api/errors/b6f6c509df400a53. Report an issue: GitHub.