Skip to content

Commit 828e8d9

Browse files
committed
fix: harden refresh_schema, _stable_document_id, get_rel_map limit
- refresh_schema(): remove broad except Exception — transport/query errors now propagate instead of silently producing an empty relationships list - _stable_document_id(): add default=str to json.dumps to handle non-JSON- serializable metadata values (datetime, UUID, Path, custom objects) - get_rel_map(): coerce limit to int() before Cypher f-string interpolation to prevent injection via non-integer caller input
1 parent 8953ce5 commit 828e8d9

2 files changed

Lines changed: 16 additions & 15 deletions

File tree

  • langchain-coordinode/langchain_coordinode
  • llama-index-coordinode/llama_index/graph_stores/coordinode

langchain-coordinode/langchain_coordinode/graph.py

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -76,19 +76,16 @@ def refresh_schema(self) -> None:
7676
# the rel_props keys returned by _parse_schema().
7777
rel_types = list(structured.get("rel_props", {}).keys())
7878
if rel_types:
79-
try:
80-
rel_filter = "|".join(_cypher_ident(t) for t in rel_types)
81-
rows = self._client.cypher(
82-
f"MATCH (a)-[r:{rel_filter}]->(b) "
83-
"RETURN DISTINCT a.__label__ AS src, r.__type__ AS rel, b.__label__ AS dst"
84-
)
85-
structured["relationships"] = [
86-
{"start": row["src"], "type": row["rel"], "end": row["dst"]}
87-
for row in rows
88-
if row.get("src") and row.get("rel") and row.get("dst")
89-
]
90-
except Exception: # noqa: BLE001
91-
pass # Graph may have no relationships yet; structured["relationships"] stays []
79+
rel_filter = "|".join(_cypher_ident(t) for t in rel_types)
80+
rows = self._client.cypher(
81+
f"MATCH (a)-[r:{rel_filter}]->(b) "
82+
"RETURN DISTINCT a.__label__ AS src, r.__type__ AS rel, b.__label__ AS dst"
83+
)
84+
structured["relationships"] = [
85+
{"start": row["src"], "type": row["rel"], "end": row["dst"]}
86+
for row in rows
87+
if row.get("src") and row.get("rel") and row.get("dst")
88+
]
9289
self._structured_schema = structured
9390

9491
def add_graph_documents(
@@ -222,12 +219,15 @@ def _stable_document_id(source: Any) -> str:
222219
content = getattr(source, "page_content", "") or ""
223220
metadata = getattr(source, "metadata", {}) or {}
224221
# Use canonical JSON encoding to avoid delimiter ambiguity and ensure
225-
# determinism for nested/non-scalar metadata values.
222+
# determinism for nested/non-scalar metadata values. default=str converts
223+
# non-JSON-serializable types (datetime, UUID, Path, …) to their string
224+
# representation so the hash never raises TypeError.
226225
canonical = json.dumps(
227226
{"content": content, "metadata": metadata},
228227
sort_keys=True,
229228
separators=(",", ":"),
230229
ensure_ascii=False,
230+
default=str,
231231
)
232232
return hashlib.sha256(canonical.encode()).hexdigest()[:32]
233233

llama-index-coordinode/llama_index/graph_stores/coordinode/base.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -203,13 +203,14 @@ def get_rel_map(
203203

204204
rel_filter = "|".join(_cypher_ident(t) for t in active_types)
205205
node_ids = [n.id for n in graph_nodes]
206+
safe_limit = int(limit) # coerce to int to prevent Cypher injection via non-integer input
206207
params: dict[str, object] = {"ids": node_ids}
207208

208209
cypher = (
209210
f"MATCH (n)-[r:{rel_filter}]->(m) "
210211
f"WHERE n.id IN $ids "
211212
f"RETURN n, r.__type__ AS _rel_type, m, n.id AS _src_id, m.id AS _dst_id "
212-
f"LIMIT {limit}"
213+
f"LIMIT {safe_limit}"
213214
)
214215
result = self._client.cypher(cypher, params=params)
215216

0 commit comments

Comments
 (0)