Before You Report a Bug, Please Confirm You Have Done The Following...
neo4j-graphrag-python's version
1.18.0
Python version
3.13.12
Operating System
Windows 11 (also reproducible on any OS)
Dependencies
fsspec==2026.6.0
neo4j==6.2.0
neo4j-graphrag==1.18.0
numpy==2.5.1
openai==1.109.1
pydantic==2.13.4
pydantic_core==2.46.4
python-dotenv==1.2.2
tenacity==9.1.4
Reproducible example
Reproduces reliably against the public demo server neo4j+s://demo.neo4jlabs.com
(recommendations database), which runs a 2026.x server whose default Cypher
language version is 5.
import neo4j
from neo4j_graphrag.embeddings import OpenAIEmbeddings
from neo4j_graphrag.retrievers import VectorRetriever
driver = neo4j.GraphDatabase.driver(
"neo4j+s://demo.neo4jlabs.com",
auth=("recommendations", "recommendations"),
)
embedder = OpenAIEmbeddings(model="text-embedding-ada-002", api_key="sk-...")
retriever = VectorRetriever(
driver=driver,
index_name="moviePlotsEmbedding", # over Movie.plotEmbedding (1536-dim)
embedder=embedder,
return_properties=["title", "year", "plot", "imdbRating"],
neo4j_database="recommendations",
)
# Raises ClientError: the generated `SEARCH ... IN (VECTOR INDEX ...)` clause
# does not parse under Cypher 5.
retriever.search(query_text="space adventure", top_k=5)
Relevant Log Output
A neo4j.exceptions.ClientError Cypher syntax error on the
SEARCH node IN (VECTOR INDEX ...) clause (Cypher 5 does not recognise it).
Because it is a syntax error rather than a PropertyNotFound, the built-in
fallback is skipped and the exception propagates.
Expected Result
The vector search succeeds (as it did before the SEARCH-clause path existed),
by using the portable CALL db.index.vector.queryNodes(...) procedure when the
server won't parse the SEARCH clause.
What happened instead?
The search raises a hard ClientError. Root cause:
supports_search_clause gates purely on the server's calendar version, not
on the effective Cypher language version:
# neo4j_graphrag/utils/version_utils.py
def supports_search_clause(driver, database=None) -> bool:
...
return version_tuple >= (2026, 1, 0)
The SEARCH ... IN (VECTOR INDEX ...) clause requires the query to run under
Cypher 25. A 2026.x server whose default language is Cypher 5 reports a
version >= (2026, 1, 0) but still rejects the clause at parse time — so
version alone is not a sufficient signal.
The only in-flight fallback is scoped to PropertyNotFound, so a syntax error
re-raises:
# neo4j_graphrag/retrievers/vector.py (get_search_results)
except neo4j.exceptions.ClientError as e:
if use_search_clause and "PropertyNotFound" in str(e):
# ... retry with the procedure-based query
else:
raise # <-- syntax errors land here and propagate
The same pattern exists in the async variant and in hybrid.py. There is also
no public constructor argument or method to force the procedure path — the only
lever is the private _node_label attribute (set in _fetch_index_infos).
Additional Info
Current workaround (relies on a private attribute):
def _force_procedure_vector_query(retriever) -> None:
# Clear the auto-detected node label so the retriever emits the portable
# CALL db.index.vector.queryNodes(...) procedure instead of the Cypher-25
# SEARCH clause.
if hasattr(retriever, "_node_label"):
retriever._node_label = None
retriever = VectorRetriever(...)
_force_procedure_vector_query(retriever)
Suggested fixes (any one resolves this):
- Widen the fallback in
get_search_results to also catch Cypher syntax
errors (not just PropertyNotFound) and retry via the procedure path.
- Detect the effective/default Cypher language version — not just the server
calendar version — in supports_search_clause, so a Cypher-5-default server
takes the procedure path.
- Expose a public opt-out, e.g.
prefer_search_clause: bool = True on the
vector/hybrid retrievers, so callers can force the portable procedure query.
Happy to open a PR for option 1 or 3 if useful.
Before You Report a Bug, Please Confirm You Have Done The Following...
neo4j-graphrag-python's version
1.18.0
Python version
3.13.12
Operating System
Windows 11 (also reproducible on any OS)
Dependencies
Reproducible example
Reproduces reliably against the public demo server
neo4j+s://demo.neo4jlabs.com(
recommendationsdatabase), which runs a 2026.x server whose default Cypherlanguage version is 5.
Relevant Log Output
A
neo4j.exceptions.ClientErrorCypher syntax error on theSEARCH node IN (VECTOR INDEX ...)clause (Cypher 5 does not recognise it).Because it is a syntax error rather than a
PropertyNotFound, the built-infallback is skipped and the exception propagates.
Expected Result
The vector search succeeds (as it did before the SEARCH-clause path existed),
by using the portable
CALL db.index.vector.queryNodes(...)procedure when theserver won't parse the SEARCH clause.
What happened instead?
The search raises a hard
ClientError. Root cause:supports_search_clausegates purely on the server's calendar version, noton the effective Cypher language version:
The
SEARCH ... IN (VECTOR INDEX ...)clause requires the query to run underCypher 25. A 2026.x server whose default language is Cypher 5 reports a
version
>= (2026, 1, 0)but still rejects the clause at parse time — soversion alone is not a sufficient signal.
The only in-flight fallback is scoped to
PropertyNotFound, so a syntax errorre-raises:
The same pattern exists in the async variant and in
hybrid.py. There is alsono public constructor argument or method to force the procedure path — the only
lever is the private
_node_labelattribute (set in_fetch_index_infos).Additional Info
Current workaround (relies on a private attribute):
Suggested fixes (any one resolves this):
get_search_resultsto also catch Cypher syntaxerrors (not just
PropertyNotFound) and retry via the procedure path.calendar version — in
supports_search_clause, so a Cypher-5-default servertakes the procedure path.
prefer_search_clause: bool = Trueon thevector/hybrid retrievers, so callers can force the portable procedure query.
Happy to open a PR for option 1 or 3 if useful.