#23073·llama_index

[Bug]: SimplePropertyGraphStore.get_rel_map returns duplicate triplets when the graph has cycles

Author: Harsh23KashyapCreated Sep 16, 2026Updated Sep 16, 2026

Bug Description

SimplePropertyGraphStore.get_rel_map walks the graph depth by depth and tracks visited triplets in seen_triplets, but the seen-set starts empty and is only updated with the next depth's triplets:

graph_triplets = self.get_triplets(ids=[gn.id for gn in graph_nodes])
seen_triplets = set()

while len(graph_triplets) > 0 and cur_depth < depth:
    triplets.extend(graph_triplets)
    graph_triplets = self.get_triplets(entity_names=[t[2].id for t in graph_triplets])
    graph_triplets = [t for t in graph_triplets if str(t) not in seen_triplets]
    seen_triplets.update([str(t) for t in graph_triplets])
    cur_depth += 1

Any path that loops back to an already-visited depth - a two-way relation, a self-loop, or any longer cycle - gets collected again at every later depth, because the starting triplets are never recorded as seen. With a simple A <-> B pair, depth=2 returns each triplet twice (see Steps to Reproduce).

The rel map is fed directly into LLM context by the property-graph sub-retrievers (indices/property_graph/sub_retrievers/llm_synonym.py, vector.py), so every duplicate is repeated relation text: wasted tokens and a skewed picture of the graph.

Proposed fix: seed seen_triplets with the starting triplets so each triplet is collected at most once across all depths. One line plus regression tests - happy to send the PR.

Version

llama-index-core 0.14.24 (also verified on current main, fd4a517)

Steps to Reproduce

from llama_index.core.graph_stores.simple_labelled import SimplePropertyGraphStore
from llama_index.core.graph_stores.types import EntityNode, Relation

store = SimplePropertyGraphStore()
a = EntityNode(name="a")
b = EntityNode(name="b")
c = EntityNode(name="c")
store.upsert_nodes([a, b, c])
store.upsert_relations([
    Relation(label="knows", source_id=a.id, target_id=b.id),
    Relation(label="knows", source_id=b.id, target_id=a.id),
    Relation(label="likes", source_id=b.id, target_id=c.id),
])

rel_map = store.get_rel_map([a], depth=2, limit=30)
for t in rel_map:
    print(t[0].name, t[1].id, t[2].name)

Output (5 triplets, the two knows relations each appear twice; expected 3 unique):

a knows b
b knows a
b likes c
a knows b
b knows a