Skip to content

Troubleshooting Queries

This guide covers how to debug and troubleshoot queries in Quine. Understanding the differences between query types helps you apply the right debugging approach.

Query Types in Quine

Quine has three types of queries, each with different troubleshooting approaches:

Query Type Description When It Runs Key Debugging Tools
Ad-hoc queries Interactive Cypher queries you run manually On-demand EXPLAIN, recentNodes()
Ingest queries Queries that execute for each record during data ingestion Per-record during ingest EXPLAIN, recentNodes()
Standing queries Incremental pattern matching that fires when data matches Continuously as data changes standing.wiretap(), recentNodes()

Ad-hoc Queries

Ad-hoc queries are interactive Cypher queries you run against the graph. Troubleshoot them when:

  • Query returns unexpected results or no results
  • Query is slow or times out
  • Query causes high resource usage

Debugging approach: Use EXPLAIN to understand the execution plan.

Ingest Queries

Ingest queries run for each record in your data pipeline. Troubleshoot them when:

  • Data isn't appearing in the graph
  • Nodes have wrong properties or missing edges
  • Ingest is slow or causing backpressure

Debugging approach: Test the query as an ad-hoc query first with sample data. Use recentNodes() to verify ingested data.

See also: Troubleshooting Ingest

Standing Queries

Standing queries incrementally match patterns as data enters the graph. Troubleshoot them when:

  • Pattern should match but doesn't fire
  • Getting unexpected matches or cancellations
  • Standing query causes performance issues

Debugging approach: First run the pattern as an ad-hoc query to verify it matches expected data. Use standing.wiretap() to stream live results.

See also: Standing Queries

Debugging Tools Reference

Tool Page Use For
EXPLAIN Query Execution Plans Understanding how queries execute
standing.wiretap() Debugging Procedures Streaming live standing query results
recentNodes() Debugging Procedures Viewing recently accessed nodes

Debugging Workflow

Follow this systematic approach when queries don't behave as expected.

Step 1: Validate Ingested Data

Before debugging queries, confirm that data is flowing into the graph correctly:

// View recently ingested nodes
CALL recentNodes(10) YIELD node
RETURN node

In the Exploration UI, double-click nodes to view their edges and hover to see properties. Verify:

  • Nodes exist with expected IDs
  • Properties have correct values and types
  • Edges connect the expected nodes

Step 2: Run as Ad-Hoc Query

If debugging a standing query or ingest query, run it as a regular Cypher query first:

// Your standing query pattern, run as ad-hoc
MATCH (order:Order)-[:PLACED_BY]->(customer:Customer)
WHERE order.total > 1000
RETURN order, customer

If this returns results but your standing query doesn't fire:

  • The data may have been ingested before the standing query was registered
  • Check if the query mode (DistinctId vs MultipleValues) is appropriate

Step 3: Analyze Query Plan

Use EXPLAIN to understand how your query executes:

EXPLAIN MATCH (order:Order)-[:PLACED_BY]->(customer:Customer)
WHERE order.total > 1000
RETURN order, customer

Look for:

  • AllNodesScan in AnchoredEntry: Consider anchoring by ID
  • Filter operators: Are conditions being applied efficiently?
  • canContainAllNodeScan: true: Query may be slow on large graphs

Common Failure Patterns

Missing Data in Graph

If ingested data doesn't appear in the graph, common causes include inconsistent idFrom usage across data sources, ingest race conditions, and edge creation that depends on property matching instead of ID lookups.

See: Troubleshooting Ingest for detailed guidance on missing data and race conditions.

Standing Query Not Matching

Symptom Cause Solution
Query works ad-hoc but not as standing query Data ingested before standing query was registered Re-ingest data or use standing.wiretap with isInitialResult
Pattern should match but doesn't Data shape doesn't match pattern exactly Run pattern as ad-hoc query to verify data matches
Matches initially then stops Negative match canceling positive match Check for data updates that invalidate the pattern

Slow Query Performance

Slow queries typically result from full graph scans, standing query backpressure, supernodes, or cross-host messaging overhead.

See: Diagnosing Bottlenecks for metrics-based diagnosis and Troubleshooting Ingest for ingest-specific optimizations.

Debugging Procedures

Quine provides several procedures for inspecting query and node state.

standing.wiretap()

Streams live results from a running standing query. This procedure runs until the standing query is canceled, emitting results incrementally as they match.

// Wiretap "hasMaternalGrandpaJoe" and return properties of matching nodes
CALL standing.wiretap({ name: "hasMaternalGrandpaJoe" }) YIELD meta, data
WHERE meta.isPositiveMatch
MATCH (n) WHERE id(n) = data.id
RETURN properties(n)

Results appear incrementally as they match. Cancel the query when you have the information you need.

Warning

The standing.wiretap procedure only stops running if the standing query is canceled (since otherwise, it can never be certain that there won't be more forthcoming match results). This means that it is risky to use the procedure in the Cypher REST API or in other places where results are not reported incrementally and queries cannot be canceled.

Return Fields

Field Type Description
meta Map Metadata including isPositiveMatch (boolean) and isInitialResult (boolean)
data Map The data returned by the standing query pattern

Results API Endpoint

Quine can stream standing query results outside of the Exploration UI using the server-sent events (SSE) endpoint:

GET /api/v1/query/standing/{standingQueryName}/results

The endpoint surfaces new matches as they are produced.

$ curl http://localhost:8080/api/v1/query/standing/hasMaternalGrandpaJoe/results
data:

data:

data:{"data":{"id":"2756309260014435"},"meta":{"isInitialResult":true,"isPositiveMatch":true,"resultId":"8f408026-8fb3-3955-c81a-7259175f41b8"}}
event:result
id:8f408026-8fb3-3955-c81a-7259175f41b8

data:{"data":{"id":"7945274922095468"},"meta":{"isInitialResult":true,"isPositiveMatch":true,"resultId":"6a83dda3-08a1-e085-ee7d-14138398f336"}}
event:result
id:6a83dda3-08a1-e085-ee7d-14138398f336

Using the SSE output, you can query the matching nodes directly:

// Query for children of nodes with IDs from the SSE endpoint above
UNWIND [2756309260014435, 7945274922095468, 6994090876991233] AS personId
MATCH (person)<-[:HAS_MOTHER|:HAS_FATHER]-(child) WHERE id(person) = personId
RETURN person.name, child.name, child.yearBorn

recentNodes()

Fetches recently accessed nodes from the in-memory cache. Useful for quickly verifying that data is being ingested:

// View recently ingested nodes
CALL recentNodes(10) YIELD node
RETURN node

In the Exploration UI, double-click nodes to view their edges and hover to see properties.