You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Inline property map in MATCH pattern silently matches nothing — should error if unsupported #1111
Environment: v0.9.0, Windows amd64, --mode moderate index.
Summary: Using an inline property map inside a MATCH pattern returns an empty result set with the generic "no results" hint, while the equivalent WHERE clause returns rows. If the Cypher subset doesn't support inline property maps, this should be a parse/validation error — silently returning 0 rows makes LLM agents (the main consumers of this tool) conclude the edges don't exist.
Repro
cli query_graph --project P --query "MATCH (a)-[r:CALLS]->(b {name: 'auto_match'}) RETURN a.qualified_name"
# → {"rows":[],"total":0,"hint":"Query returned no results..."} ← silent empty
cli query_graph --project P --query "MATCH (a)-[r:CALLS]->(b) WHERE b.name = 'auto_match' RETURN a.qualified_name"
# → 2 rows (correct)
Related: RETURN type(r) also doesn't resolve (returns the row count in both columns instead of the relationship type) — same "unsupported syntax should error, not mislead" argument:
cli query_graph --project P --query "MATCH ()-[r]->() RETURN type(r) AS tipo, count(*) AS n ORDER BY n DESC"
# → {"columns":["tipo","n"],"rows":[["176178","176178"]],"total":1}
Suggested fix: either support inline property maps (they're the most common Cypher idiom LLMs emit) or reject them with an explicit error listing the supported subset.
Thanks for the precise paired queries. This is a high-priority 0.9.1-rc correctness bug: unsupported syntax must not silently produce authoritative-looking empty or fabricated results. Please keep the inline property-map case and type(r) case as separate RED assertions because they exercise different parser/evaluator paths. The fix may implement the syntax or fail closed with a specific unsupported-syntax error, but it must not return a successful misleading result.
Confirming the inline-property-map half on the released RC, not just on HEAD — and reporting that the original repro in this issue was conflating two separate defects.
Environment: v0.9.1-rc.1, Windows amd64, ui variant, --mode moderate, indexed into an isolated CBM_CACHE_DIR. Corpus: a real Python/TypeScript repo, 13,475 nodes / 49,261 edges.
The inline map works now
Target with 81 callers (ground truth from RETURN b.name AS n, count(*) AS c, which groups correctly):
query
rows
MATCH (a:Function)-[r:CALLS]->(b:Function {name:'set_schema'}) RETURN a.qualified_name
81
MATCH (a:Function)-[r:CALLS]->(b:Function) WHERE b.name='set_schema' RETURN a.qualified_name
81
MATCH (a)-[r:CALLS]->(b {name:'set_schema'}) RETURN a.qualified_name — the shape reported here
81
MATCH (a)-[r:CALLS]->(b) WHERE b.name='set_schema' RETURN a.qualified_name
81
So closing this half is justified. Two follow-ups.
The v0.9.0 repro had no label on the source node — the #1196 shape
That is very likely why the two halves behaved as one back then. On this build the mechanisms separate cleanly: inline maps resolve, and what remains is #1196's scan-budget truncation, still reproducing on the RC. Same repo, target with 1,140 callers:
Why this matters for the acceptance criteria of this issue: the 81-caller target above passes in all four forms because its candidate population fits inside the default budget. A regression test for inline property maps built on a small fixture will therefore pass whether or not inline maps work at all. To be a genuine RED assertion it needs either a target whose candidate population exceeds max_rows, or a labeled source node so #1196 cannot mask the outcome.
Request
The inline-map case is confirmed working, but it landed without an assertion — b43bddd adds only the two type(r) tests, and the commit message closes this half as not reproducing. Given the contract stated above in this thread (unsupported or unresolved syntax must not return a successful misleading result), could an assertion be added for it, or the case tracked wherever that contract is pinned? As it stands nothing prevents a silent regression, and silence is exactly the failure mode this issue was opened about.
type(r), for anyone arriving here from the RC
Still broken on v0.9.1-rc.1, since b43bddd merged after the RC was cut: MATCH (a)-[r]->(b) RETURN type(r) AS t, count(*) AS n ORDER BY n DESC returns a single row whose both columns read 49261 — the total edge count.
The #1358 workaround holds on this build: MATCH (a)-[r]->(b) WITH type(r) AS t RETURN t, count(*) AS c ORDER BY c DESC → 25 correct rows (DEFINES 13691, CALLS 13030, USAGE 8737, …).
Worth noting the workaround is narrower than it looks: moving the aggregate into the WITH (WITH type(r) AS t, count(*) AS n RETURN t, n) still fabricates the single 49261/49261 row. That path appears to be covered by the with_agg_* call sites in the merge, so it should be fixed too — but it is worth its own assertion, since users reaching for the workaround are one keystroke away from the same wrong answer.
Activity
DeusData commentedon Jul 16, 2026
Thanks for the precise paired queries. This is a high-priority 0.9.1-rc correctness bug: unsupported syntax must not silently produce authoritative-looking empty or fabricated results. Please keep the inline property-map case and
type(r)case as separate RED assertions because they exercise different parser/evaluator paths. The fix may implement the syntax or fail closed with a specific unsupported-syntax error, but it must not return a successful misleading result.fix(cypher): classify aggregation columns by is_aggregate_func, not a…
junk151516 commentedon Jul 31, 2026
Confirming the inline-property-map half on the released RC, not just on HEAD — and reporting that the original repro in this issue was conflating two separate defects.
Environment: v0.9.1-rc.1, Windows amd64,
uivariant,--mode moderate, indexed into an isolatedCBM_CACHE_DIR. Corpus: a real Python/TypeScript repo, 13,475 nodes / 49,261 edges.The inline map works now
Target with 81 callers (ground truth from
RETURN b.name AS n, count(*) AS c, which groups correctly):MATCH (a:Function)-[r:CALLS]->(b:Function {name:'set_schema'}) RETURN a.qualified_nameMATCH (a:Function)-[r:CALLS]->(b:Function) WHERE b.name='set_schema' RETURN a.qualified_nameMATCH (a)-[r:CALLS]->(b {name:'set_schema'}) RETURN a.qualified_name— the shape reported hereMATCH (a)-[r:CALLS]->(b) WHERE b.name='set_schema' RETURN a.qualified_nameSo closing this half is justified. Two follow-ups.
The v0.9.0 repro had no label on the source node — the #1196 shape
That is very likely why the two halves behaved as one back then. On this build the mechanisms separate cleanly: inline maps resolve, and what remains is #1196's scan-budget truncation, still reproducing on the RC. Same repo, target with 1,140 callers:
Why this matters for the acceptance criteria of this issue: the 81-caller target above passes in all four forms because its candidate population fits inside the default budget. A regression test for inline property maps built on a small fixture will therefore pass whether or not inline maps work at all. To be a genuine RED assertion it needs either a target whose candidate population exceeds
max_rows, or a labeled source node so #1196 cannot mask the outcome.Request
The inline-map case is confirmed working, but it landed without an assertion — b43bddd adds only the two
type(r)tests, and the commit message closes this half as not reproducing. Given the contract stated above in this thread (unsupported or unresolved syntax must not return a successful misleading result), could an assertion be added for it, or the case tracked wherever that contract is pinned? As it stands nothing prevents a silent regression, and silence is exactly the failure mode this issue was opened about.type(r), for anyone arriving here from the RCStill broken on v0.9.1-rc.1, since b43bddd merged after the RC was cut:
MATCH (a)-[r]->(b) RETURN type(r) AS t, count(*) AS n ORDER BY n DESCreturns a single row whose both columns read49261— the total edge count.The #1358 workaround holds on this build:
MATCH (a)-[r]->(b) WITH type(r) AS t RETURN t, count(*) AS c ORDER BY c DESC→ 25 correct rows (DEFINES13691,CALLS13030,USAGE8737, …).Worth noting the workaround is narrower than it looks: moving the aggregate into the
WITH(WITH type(r) AS t, count(*) AS n RETURN t, n) still fabricates the single49261/49261row. That path appears to be covered by thewith_agg_*call sites in the merge, so it should be fixed too — but it is worth its own assertion, since users reaching for the workaround are one keystroke away from the same wrong answer.