Summary
When the grouping key in RETURN is a function call rather than a property, the executor does not group. It returns a single row and writes the aggregate value into the non-aggregate column. No error is raised.
Repro
query_graph --query "MATCH (n) RETURN labels(n) AS label, count(*) AS c ORDER BY c DESC"
Actual:
{"columns":["label","c"],"rows":[["21143","21143"]]}
Expected: one row per label — ["Function", 14960], ["Variable", 1747], ["Macro", 1066], … (these counts are correct and are what get_graph_schema reports).
What does work
labels(n) as a plain projection: MATCH (n:Function) RETURN labels(n) LIMIT 1 -> ["Function"]
- Property-based grouping:
MATCH (n) RETURN n.file_path, count(*) -> correct per-file counts
Both halves work in isolation; only the combination fails.
Why this matters
The failure is silent. The caller receives a well-formed result with a plausible-looking number in it, so an LLM agent consuming this reports the wrong answer confidently. The engine already rejects unsupported constructs loudly and correctly (CREATE -> unsupported Cypher feature: CREATE clause); an unsupported ... error here would be strictly better than a wrong row.
Environment
- Version: codebase-memory-mcp 0.9.0 (release binary, darwin-arm64)
- OS: macOS 26.5.2, Apple Silicon
- Repo under test: DeusData/codebase-memory-mcp @ af3ffbd (21,143 nodes / 123,103 edges)
- Verified identically through both the MCP server and
cli mode (outputs byte-identical)
Summary
When the grouping key in
RETURNis a function call rather than a property, the executor does not group. It returns a single row and writes the aggregate value into the non-aggregate column. No error is raised.Repro
Actual:
{"columns":["label","c"],"rows":[["21143","21143"]]}Expected: one row per label —
["Function", 14960],["Variable", 1747],["Macro", 1066], … (these counts are correct and are whatget_graph_schemareports).What does work
labels(n)as a plain projection:MATCH (n:Function) RETURN labels(n) LIMIT 1->["Function"]MATCH (n) RETURN n.file_path, count(*)-> correct per-file countsBoth halves work in isolation; only the combination fails.
Why this matters
The failure is silent. The caller receives a well-formed result with a plausible-looking number in it, so an LLM agent consuming this reports the wrong answer confidently. The engine already rejects unsupported constructs loudly and correctly (
CREATE->unsupported Cypher feature: CREATE clause); anunsupported ...error here would be strictly better than a wrong row.Environment
climode (outputs byte-identical)