Summary
find_code's repo_path filter silently returns 0 results when passed a repo name or relative path — with no error. It only works if the caller passes the exact absolute path that was used as the indexing root, which isn't what other tools return in a directly reusable form.
Root cause
Across src/codegraphcontext/tools/code_finder.py (find_by_function_name, find_by_class_name, find_by_variable_name, find_by_content, and ~20 other query sites), the filter is:
repo_filter = "AND node.path STARTS WITH $repo_path" if repo_path else ""
repo_path is used verbatim, with no normalization, as a raw string prefix against the stored .path property. Indexed node paths are stored as the absolute filesystem path used at indexing time (e.g. /data/repos/service-a/module/file.py). If a caller passes anything other than that exact absolute prefix — a bare repo name, a relative path, a path with different casing/trailing slash — the STARTS WITH comparison matches nothing, and the tool returns an empty result set indistinguishable from "no matches exist."
There's a separate, unrelated .resolve() call in code_finder.py (in audit_kotlin_call_ambiguity) that resolves a relative repo_path against the process cwd — that one has its own bug (wrong resolution base) but is a different code path from find_code/find_related_code, which has no resolution step at all.
Repro (verified locally, current main @ 810ea8a, v0.5.8, KuzuDB backend)
db = KuzuDBManager(db_path="<scratch-db>")
cf = CodeFinder(db)
cf.find_related_code("SomeClass", False, 2, repo_path=None)
# -> total_matches=4 (baseline: query alone works)
cf.find_related_code("SomeClass", False, 2, repo_path="service_a")
# -> total_matches=0 (short repo name — silently empty)
cf.find_related_code("SomeClass", False, 2, repo_path="/abs/path/to/repro-repo/service_a")
# -> total_matches=4 (exact absolute index root — works)
Repo was indexed via cgc index service_a (repo containing one file with a SomeClass class). cgc list afterward shows the repo's Path column as the absolute path — so even copying that exact displayed value works, but the natural/short form (repo name, or a relative path a user might type) does not, and nothing in the tool response indicates why.
Originally observed against a Neo4j-backed MCP server (0.5.3-ish); reproduced independently against KuzuDB on latest main — so this is backend-independent and still present at HEAD.
Impact
Any caller that filters find_code by repo — using the repo name from list_indexed_repositories/cgc list, or any path not byte-identical to the original indexing root — gets an empty result for real, indexed content, with no error or warning. This is worse than a hard failure since it looks like "no matches" rather than "wrong filter."
Suggested fix
- Normalize both sides consistently: store/compare canonical (resolved, OS-normalized) paths, and normalize incoming
repo_path the same way before filtering — resolving against the repo's known indexed root (looked up by repo name), not the caller's cwd or a raw string.
- At minimum, when
repo_path doesn't correspond to any indexed path (as a full prefix or by repo-name lookup), return a clear error/warning instead of a silent empty match.
- Consider accepting repo name (as shown by
list_indexed_repositories) as first-class input, resolved server-side to whatever root path is actually stored — most callers won't know or want to reconstruct the original absolute indexing path.
Environment
codegraphcontext version: 0.5.8 (main @ 810ea8a), also separately reproduced against a Neo4j-backed 0.5.3-class deployment
- Graph DB backends tested: Neo4j (original report) and KuzuDB (this repro)
- OS: macOS (Darwin)
Summary
find_code'srepo_pathfilter silently returns 0 results when passed a repo name or relative path — with no error. It only works if the caller passes the exact absolute path that was used as the indexing root, which isn't what other tools return in a directly reusable form.Root cause
Across
src/codegraphcontext/tools/code_finder.py(find_by_function_name,find_by_class_name,find_by_variable_name,find_by_content, and ~20 other query sites), the filter is:repo_pathis used verbatim, with no normalization, as a raw string prefix against the stored.pathproperty. Indexed node paths are stored as the absolute filesystem path used at indexing time (e.g./data/repos/service-a/module/file.py). If a caller passes anything other than that exact absolute prefix — a bare repo name, a relative path, a path with different casing/trailing slash — theSTARTS WITHcomparison matches nothing, and the tool returns an empty result set indistinguishable from "no matches exist."There's a separate, unrelated
.resolve()call incode_finder.py(inaudit_kotlin_call_ambiguity) that resolves a relativerepo_pathagainst the process cwd — that one has its own bug (wrong resolution base) but is a different code path fromfind_code/find_related_code, which has no resolution step at all.Repro (verified locally, current main @
810ea8a, v0.5.8, KuzuDB backend)Repo was indexed via
cgc index service_a(repo containing one file with aSomeClassclass).cgc listafterward shows the repo'sPathcolumn as the absolute path — so even copying that exact displayed value works, but the natural/short form (repo name, or a relative path a user might type) does not, and nothing in the tool response indicates why.Originally observed against a Neo4j-backed MCP server (0.5.3-ish); reproduced independently against KuzuDB on latest main — so this is backend-independent and still present at HEAD.
Impact
Any caller that filters
find_codeby repo — using the repo name fromlist_indexed_repositories/cgc list, or any path not byte-identical to the original indexing root — gets an empty result for real, indexed content, with no error or warning. This is worse than a hard failure since it looks like "no matches" rather than "wrong filter."Suggested fix
repo_paththe same way before filtering — resolving against the repo's known indexed root (looked up by repo name), not the caller's cwd or a raw string.repo_pathdoesn't correspond to any indexed path (as a full prefix or by repo-name lookup), return a clear error/warning instead of a silent empty match.list_indexed_repositories) as first-class input, resolved server-side to whatever root path is actually stored — most callers won't know or want to reconstruct the original absolute indexing path.Environment
codegraphcontextversion: 0.5.8 (main @810ea8a), also separately reproduced against a Neo4j-backed 0.5.3-class deployment