Skip to content

query_graph: patterns with no label on the source node silently return empty — same DB and binary previously returned correct rows (v0.9.0) #1196

Description

@junk151516

Environment: v0.9.0, Windows amd64 (ui variant), same index DB as #1110 / #1132 / #1133 (10 projects; main graph 31k nodes / 176k edges, 43,851 CALLS edges per get_graph_schema). The CLI and the MCP server return identical results. First mentioned in #1110 (comment) — filing it on its own as it's unrelated to the (invalid) direction flag discussed there.

Summary: On 2026-07-15 this query returned 2 correct rows (documented verbatim in #1110's body):

MATCH (a)-[r:CALLS]->(b) WHERE b.name = 'auto_match' RETURN a.qualified_name   → 2 rows (correct)

Today, same binary (SHA-pinned) and same project, it returns {"rows":[],"total":0} with the generic no-results hint. Probe matrix:

Query shape Result
MATCH (n) RETURN n.name ✅ rows
MATCH (n) WHERE n.name = '<existing>' RETURN ... ❌ silent empty
MATCH (n) WHERE n.lines > 100 RETURN ... ❌ silent empty
MATCH (n:Method) WHERE n.name = '<same>' RETURN ... ✅ 1 row
MATCH (a)-[r]->(b) RETURN a.name (untyped edge) ✅ rows
MATCH (a)-[r:CALLS]->(b) RETURN a.name ❌ silent empty
MATCH (a:Function)-[r:CALLS]->(b) RETURN a.name, b.name ✅ rows
MATCH (a:Function)-[r:CALLS]->(b) WHERE b.name = 'X' RETURN ... ✅ correct callers (verified vs grep)
MATCH (a)-[r:CALLS]->(b:Method) WHERE b.name = 'X' RETURN ... ❌ silent empty (label on the TARGET doesn't help)

Reproduced identically on a second project in the same DB (13.5k nodes), for string and numeric predicates, via both the CLI and the MCP server.

What changed between "worked" (2026-07-15) and "broken" (2026-07-21): not the binary. The DB went through several delete_project + fresh-index cycles (projects added and removed on 2026-07-16) plus incremental auto-watch updates. It looks like whatever powers unlabeled scans / typed-edge anchor selection consults per-label state that goes stale after those cycles, while label-anchored plans still read the live data.

Impact: the most natural Cypher an LLM agent emits (MATCH (a)-[:CALLS]->(b) WHERE b.name = ...) now silently reads as "no callers" — the same confidently-wrong-empty failure family as #1111 / #1133. Workaround: always put a label on the pattern's source node.

Asks:

  1. Make unlabeled matching consistent with label-anchored matching after delete/reindex cycles (or rebuild the relevant index on write).
  2. Until then, fail explicit: if the planner resolves a zero-cardinality anchor while the schema reports non-empty labels/edge types, return an error or a diagnostic instead of a clean empty set.

Happy to run a diagnostic build against this DB — it's private, but I can run anything read-only and share the output.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workingcypherCypher query language parser/executor bugsparsing/qualityGraph extraction bugs, false positives, missing edgespriority/highNeeds near-term maintainer attention; high-impact bug, regression, safety issue, or release blocker.ux/behaviorDisplay bugs, docs, adoption UXwindowsWindows-specific issues

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions