{"record":{"id":"b6f6c509df400a53","repo":"zed-industries/zed","slug":"invalid-glob-err","errorCode":null,"errorMessage":"Invalid glob: {err}","messagePattern":"Invalid glob: (.+?)","errorType":"validation","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"crates/agent/src/tools/find_path_tool.rs","lineNumber":192,"sourceCode":"                offset: input.offset,\n                current_matches_page: paginated_matches.to_vec(),\n                all_matches_len: matches.len(),\n            })\n        })\n    }\n}\n\nfn search_paths(glob: &str, project: Entity<Project>, cx: &mut App) -> Task<Result<Vec<PathBuf>>> {\n    let path_style = project.read(cx).path_style(cx);\n    let path_matcher = match PathMatcher::new(\n        [\n            // Sometimes models try to search for \"\". In this case, return all paths in the project.\n            if glob.is_empty() { \"*\" } else { glob },\n        ],\n        path_style,\n    ) {\n        Ok(matcher) => matcher,\n        Err(err) => return Task::ready(Err(anyhow!(\"Invalid glob: {err}\"))),\n    };\n    let snapshots: Vec<_> = project\n        .read(cx)\n        .worktrees(cx)\n        .map(|worktree| worktree.read(cx).snapshot())\n        .collect();\n\n    cx.background_spawn(async move {\n        let mut results = Vec::new();\n        for snapshot in snapshots {\n            for entry in snapshot.entries(false, 0) {\n                if path_matcher.is_match(&snapshot.root_name().join(&entry.path)) {\n                    results.push(snapshot.absolutize(&entry.path));\n                }\n            }\n        }\n\n        Ok(results)","sourceCodeStart":174,"sourceCodeEnd":210,"githubUrl":"https://github.com/zed-industries/zed/blob/bc538def4545534201bbfcac4e95ac34ea6501b6/crates/agent/src/tools/find_path_tool.rs#L174-L210","documentation":"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.","triggerScenarios":"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.","commonSituations":"LLM-generated patterns confusing regex and glob syntax; Windows/Unix separator confusion; nested brace expansions the matcher does not support.","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."],"exampleFix":"# before\nfind_path(pattern=\".*\\\\.rs$\")   # regex — Invalid glob\nfind_path(pattern=\"[a-z\")       # unbalanced bracket\n\n# after\nfind_path(pattern=\"**/*.rs\")","handlingStrategy":"validation","validationCode":"let effective_glob = if glob.is_empty() { \"*\" } else { glob };\nif let Err(err) = PathMatcher::new([effective_glob], path_style) {\n    anyhow::bail!(\"invalid glob {glob:?}: {err}\");\n}","typeGuard":"fn is_valid_glob(glob: &str, path_style: PathStyle) -> bool {\n    let effective = if glob.is_empty() { \"*\" } else { glob };\n    PathMatcher::new([effective], path_style).is_ok()\n}","tryCatchPattern":null,"preventionTips":["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."],"tags":["glob","filesystem","validation","tooling"],"backgroundTag":null,"analyzedSha":"bc538def4545534201bbfcac4e95ac34ea6501b6","analyzedAt":"2026-08-16T07:30:46.435Z","schemaVersion":2},"datasetVersion":"2026-08-16T08:17:34.114Z"}