Do you need to file an issue?
Describe the bug
graphrag update runs the full pipeline over the new document alone, minting fresh UUIDs,
then merges the result into the existing index. The entity merge keeps the pre-existing row
on a title collision, discards the delta UUID and returns a {delta_id: old_id} mapping.
The community merge never receives it, so delta communities are concatenated with their
entity_ids and relationship_ids still pointing at the discarded ids.
Minimal example
Initial graphrag index over document A:
entities ALPHA id=e-1, BETA id=e-2
communities community 0 -> entity_ids [e-1, e-2]
graphrag update with document B, which mentions ALPHA and GAMMA. The delta run has no
knowledge of the existing index, so it mints new ids and clusters its own graph:
delta entities ALPHA id=d-1, GAMMA id=d-2
delta communities community 0 -> entity_ids [d-1, d-2]
After the merge:
entities ALPHA id=e-1 (d-1 discarded; mapping {d-1: e-1} produced)
BETA id=e-2
GAMMA id=d-2
communities community 0 -> entity_ids [e-1, e-2]
community 1 -> entity_ids [d-1, d-2] <-- d-1 resolves to nothing
Root cause
_group_and_resolve_entities keeps the old row on a title collision and returns
{delta_id: old_id}:
id_mapping = dict(zip(merged["id_B"], merged["id_A"])) # delta -> old
...
.groupby("title").agg({"id": "first", ...}) # old row wins
The mapping is published to the run state in update_entities_relationships.py, and applied
in exactly one place: update_text_units.py. _update_and_merge_communities never touches
entity_ids or relationship_ids; they ride through the concatenation unchanged.
Relationships are worse off: _update_and_merge_relationships uses the same "id": "first"
collision handling but returns only a DataFrame, so no relationship mapping exists at all.
Impact
- ALPHA is never linked to community 1, although the report for community 1 was generated
from ALPHA's delta description and refers to it.
communities.size for community 1 says 2; only one member is resolvable.
- The same applies to
relationship_ids for any edge present in both documents.
Related issues
Steps to reproduce
graphrag index a corpus containing at least one entity that will also appear in a second
document.
- Add the second document and run
graphrag update.
- Read
communities.parquet and entities.parquet, and explode entity_ids:
import pandas as pd
e = pd.read_parquet("output/entities.parquet")
c = pd.read_parquet("output/communities.parquet")
exploded = c.explode("entity_ids")
dangling = exploded[~exploded["entity_ids"].isin(set(e["id"]))]
print(dangling[["community", "entity_ids"]])
Every row printed is a community member that no query path can resolve. The count grows with
each subsequent update.
Expected Behavior
Community membership lists should reference the ids that survived the entity and relationship
merges, so that entities carried over from a previous run remain linked to the communities the
delta run placed them in.
Do you need to file an issue?
Describe the bug
graphrag updateruns the full pipeline over the new document alone, minting fresh UUIDs,then merges the result into the existing index. The entity merge keeps the pre-existing row
on a title collision, discards the delta UUID and returns a
{delta_id: old_id}mapping.The community merge never receives it, so delta communities are concatenated with their
entity_idsandrelationship_idsstill pointing at the discarded ids.Minimal example
Initial
graphrag indexover document A:graphrag updatewith document B, which mentions ALPHA and GAMMA. The delta run has noknowledge of the existing index, so it mints new ids and clusters its own graph:
After the merge:
Root cause
_group_and_resolve_entitieskeeps the old row on a title collision and returns{delta_id: old_id}:The mapping is published to the run state in
update_entities_relationships.py, and appliedin exactly one place:
update_text_units.py._update_and_merge_communitiesnever touchesentity_idsorrelationship_ids; they ride through the concatenation unchanged.Relationships are worse off:
_update_and_merge_relationshipsuses the same"id": "first"collision handling but returns only a DataFrame, so no relationship mapping exists at all.
Impact
from ALPHA's delta description and refers to it.
communities.sizefor community 1 says 2; only one member is resolvable.relationship_idsfor any edge present in both documents.Related issues
read_indexer_entitiesthat resolves community membership by entity id.
Confirms that an id which fails to resolve raises nothing and logs nothing; entities left
with
level = NaNare silently dropped bydf[df.level <= community_level].accepted and fixed. The function quoted there,
_update_and_merge_text_units, is the onlyplace
entity_id_mappingis applied today.Steps to reproduce
graphrag indexa corpus containing at least one entity that will also appear in a seconddocument.
graphrag update.communities.parquetandentities.parquet, and explodeentity_ids:Every row printed is a community member that no query path can resolve. The count grows with
each subsequent
update.Expected Behavior
Community membership lists should reference the ids that survived the entity and relationship
merges, so that entities carried over from a previous run remain linked to the communities the
delta run placed them in.