[BUG] group_id selects a database for writes but not for reads: add_episode persists to the cloned database, search/get_episodes query the configured one
Problem
add_episode resolves a per-group database, but read paths do not. Writes and reads therefore target different databases whenever group_id differs from the driver's configured database, and reads come back empty with no error.
_resolve_request_scope (added in #1699 to fix #1676) clones the driver per call:
if group_id == self.driver._database:
return group_id, self.driver, self.clients
driver = self.driver.clone(database=group_id)
clients = self.clients.model_copy(update={'driver': driver})
return group_id, driver, clientsOnly add_episode and add_episode_bulk call it. The read paths do not:
Graphiti.search()passesself.clientsand an optional caller-supplieddriver; it never derives one fromgroup_ids.- The MCP server's
get_episodescallsEpisodicNode.get_by_group_ids(client.driver, ...)on the base driver.
So an episode written under group_id="X" lands in database X, while a read for group_ids=["X"] runs against the configured database and finds nothing.
Reproduction
Using the MCP server against FalkorDB with a deliberate mismatch:
FALKORDB_DATABASE=smoke_dbGRAPHITI_GROUP_ID=smoke_0302
Steps:
add_memorythree episodes. Each reports success, and the server logsSuccessfully processed episode ... for group smoke_0302.GRAPH.LISTshows two graphs,smoke_dbandsmoke_0302. All threeEpisodicnodes are insmoke_0302, confirming the write clone worked.get_episodesreturnsNo episodes foundforgroup_ids="smoke_0302", for["smoke_0302"], and for the default.
Expected: the episodes just written are returned. Actual: nothing, with no error.
Why this is easy to miss
The single-database deployment is unaffected: when group_id equals the configured database, _resolve_request_scope returns the shared driver unchanged, so writes and reads agree. The failure needs group_id != database, which is exactly the multi-tenant shape #1676 was about.
It also fails silently. Ingestion reports success, the data is genuinely persisted, and the read returns an empty result rather than an error — so it presents as "memory not working" rather than as a misconfiguration.
Suggested fix
Resolve the request scope on read paths too, so a group_id selects the same database for reads as for writes. Two shapes seem plausible:
- Have
search()/search_()and the episode accessors derive the driver fromgroup_idsthe wayadd_episodedoes, when a singlegroup_idis given. - Or reject the mismatch at construction time, if targeting a database other than the one a
group_idmaps to is meant to be unsupported.
The choice depends on whether group_id is intended to name the database or merely to partition within it. Right now the write path treats it as the former and the read path as the latter, and that disagreement is the bug.
Related
- #1676 — concurrent multi-
group_idisolation, the original report - #1699 — the fix, which covered the write path
Source: getzep/graphiti