Repository navigation
Description
query_graph / search_graph return "project not found or not indexed" even with a registered, indexed project
Environment
- Tool:
codebase-memory-mcpv0.8.1 (binary download from release, macOS aarch64) - OS: macOS 15 (Darwin), APFS filesystem (default case-insensitive, case-preserving)
- Storage dir:
~/.cache/codebase-memory-mcp/ - Project indexed: MSBA-MSBA (3034
.csfiles, 82,303 nodes / 269,108 edges perlist_projects)
Repro
- Install cbm 0.8.1 per the official script (single static binary).
- Index a repo:
codebase-memory-mcp cli index_repository '{"repo_path":"/path/to/MSBA-MSBA"}'— succeeds, list_projects shows it. - Within the same shell session (or the same batch job that called index_repository), run:
→ returns 35 results, exit=0.
codebase-memory-mcp cli search_graph '{"name_pattern":"DTO$","label":"Class","limit":100,"project":"Users-...-MSBA-MSBA"}' - Wait 10 minutes (or close/reopen the shell).
- Run the exact same command again →
{"error":"project not found or not indexed", "available_projects":[...the same 4 entries...]}
What's odd
list_projectskeeps showing the project (fullnodes/edges/size_bytesmetadata present)._config.dbis empty (SELECT * FROM config→ 0 rows in~/.cache/codebase-memory-mcp/_config.db).- The per-project SQLite DB (
Users-...-MSBA-MSBA.db, ~282 MB) is still on disk, populated, the same content as before —filereports it as a validSQLite 3.x database. - Trying
codebase-memory-mcp config set project "<name>"andconfig reset projectdoes not change anything. - Tried 8 variations of the
projectparameter naming (project,project_name,project_id,projectName,projectPath,root_path) — every form is rejected with the same error.
Smell-test observations from a CI run on 2026-06-29
I ran a 120-combo benchmark (3 tools × 4 repos × 10 probes) using cbm via the same CLI wrapper. During the run (~7 min), all search_graph/query_graph calls inside the bench returned 200-class responses with parsed matches; 5 minutes after the run finished, the exact same CLI invocations started failing.
I noticed two files with display name Users-...-MSBA-MSBA.db in the cache dir, differing only in character class:
| inode | size | path byte sequence |
|---|---|---|
| 100978290 | 295895040 | ...matias.nah**u**el**.amendola**-Projects-...-MSBA-MSBA.db (note the . after el) |
| 101033163 | 0 | ...matias.nah**u**el**-amendola**-Projects-...-MSBA-MSBA.db (note the - after el) |
So list_projects returns 5 entries (one of them is the empty …el-amendola… path), and query_graph "knows about" the populated project (Users-...-MSBA-MSBA.db) but the second …el-amendola… shadow-DB confuses the lookup.
This appears to be a filesystem path normalization issue (Unicode NFD/NFC? Or HFS+'s case-insensitivity creation semantics?) where the CLI picks up a different on-disk file depending on how the path is being passed (env-var vs cmdline-arg vs working-dir-relative), and the wrong one wins.
Probable root cause
The CLI binary must be doing one of:
realpath()on the project argument, then normalizing against an HFS-/APFS-canonical form different from what was used during index time.- Comparing only by
display_name(which collides under case-insensitive filesystems) rather than inode/path. - Maintaining an in-memory registry that's only consistent within a single process (the bench's per-process state had the right pointer; subsequent fresh processes have a different one).
Evidence
Bench JSON proving the query path worked once:
cbm-MSBA-MSBA-inconsistency_dto_rename.json→ 35 matches withqualified_namepopulated, exit_code=0,command=[...cli, search_graph, '{\"name_pattern\": \"DTO$\", \"label\": \"Class\", \"limit\": 100, \"project\": \"Users-...-MSBA-MSBA\"}']
After the run, the same command returns:
- exit_code=1, stderr=
{"error":"project not found or not indexed","hint":"Use list_projects...","available_projects":["...", "...", ..., "Users-...-MSBA-MSBA"]}
What I'd like
A fix (or workaround doc) for one of:
- CLI: cache the project registry to disk so it survives process boundaries.
- Path normalization: canonicalize project paths the same way at index and query time (suggested: compare by inode/mtime, not path bytes).
- Workaround doc: how to invoke cbm CLI so the project lookup is robust against the in-memory-only registry.
Environment
$ codebase-memory-mcp --version
codebase-memory-mcp 0.8.1
$ uname -a
Darwin Mac 24.x ... aarch64
Thanks — happy to test any fix on my end.
Activity
DeusData commentedon Jun 30, 2026
Thanks for the detailed report. I’ve triaged this as a project-identity / path-normalization bug:
list_projectscan still see the DB, but query tools appear to resolve or open a different derived project DB after the original process is gone.I’m linking this under the query-resolution and UX trackers. The regression guard should cover: index a project, start a fresh process later, run the same
search_graph/query_graph, and verify it opens the populated DB even when a zero-byte shadow DB or APFS-normalized path variant exists. In the meantime, removing the zero-byte shadow DB and re-indexing from one canonical absolute path may be the safest workaround.Merge pull request #717 from DeusData/fix/704-store-resolution
DeusData commentedon Jun 30, 2026
Fixed in ad422bc (PR #717). Project resolution now keys on the db's INTERNAL project name (the
projects.namerow), not the.dbfilename — solist_projects, the resolver, and node queries all agree even when a db's filename drifted from its internal name (the.-vs--username twin, or a copied/renamed db). Ghost dbs (0-byte/empty) are filtered from the list; no file renames or data mutation. (The empty_config.dbyou spotted is a red herring — it's a KV settings store, never a registry.) The separate latent bug where queries opened the db read-write — mutating it and failing on a read-only FS — is fixed in #719. Ships next release — thanks for the thorough diagnosis.fix(mcp): resolve projects by internal name + filter ghost dbs (DeusD…
fix(store): open query stores READONLY so queries never mutate dbs
fix(mcp): resolve project arg by unique name tail when exact lookup m…
fix(mcp): resolve project arg by unique name tail when exact lookup m…
fix(mcp): ignore ::missed shadow rows when resolving a db's project name
fix(hqm): B19 - a coverage shadow row made list_projects drop the db …
fix(mcp): non-mutating query-only store resolve; annotate the ten rea…
fix(mcp): non-mutating query-only store resolve; annotate the ten rea…
fix(mcp): non-mutating query-only store resolve; annotate the ten rea…
DeusData commentedon Sep 3, 2026
A follow-on improvement to the exact symptom reported here landed on main today in
f37a47eb(PR #1871, thanks @LazyXuan).This issue was about
query_graph/search_graphreporting "project not found" while the databases were valid on disk. That message is now gone for the corrupt-store case: a query whose store fails its integrity check reportsproject store is corrupt (left untouched); run index_repository to rebuild itinstead — which says what actually happened and what to do about it, rather than implying the project was never indexed.The change underneath it matters too. The query path no longer opens the store writably at all when integrity fails: it closes and reopens through a query-only handle, so a corrupt database is inspected without any possibility of the recovery path quarantining files behind a read-only-looking call. Recording it here in case anyone arrives at this issue from a search.