googleapis/mcp-toolbox · error
dry-run produced an empty execution plan
Error message
dry-run produced an empty execution plan
What it means
During a dry run, after an execution plan is obtained, RunCypher counts the plan's operators via buildPlanNode. If operatorCount is 0 the plan exists but is empty, so there is nothing meaningful to report — the tool rejects the dry-run result with this error. It guards against returning a useless empty plan structure to callers.
Source
Thrown at internal/sources/arcadedb/arcadedb.go:156
}
config := neo4j.ExecuteQueryWithDatabase(s.ArcadeDBDatabase())
results, err := neo4j.ExecuteQuery[*neo4j.EagerResult](ctx, s.ArcadeDBDriver(), cypherStr, params,
neo4j.EagerResultTransformer, config)
if err != nil {
return nil, fmt.Errorf("unable to execute query: %w", err)
}
if dryRun {
summary := results.Summary
plan := summary.Plan()
if plan == nil {
return nil, fmt.Errorf("dry-run produced no execution plan")
}
node, incomplete, operatorCount := buildPlanNode(plan)
if operatorCount == 0 {
return nil, fmt.Errorf("dry-run produced an empty execution plan")
}
execPlan := map[string]any{
"queryType": cf.Type.String(),
"statementType": summary.QueryType(),
}
for k, v := range node {
execPlan[k] = v
}
if incomplete {
execPlan["plan_incomplete"] = true
execPlan["warning"] = "Execution plan appears partial; server may not provide complete EXPLAIN details for this query/version."
}
return []map[string]any{execPlan}, nil
}
return formatRecords(results.Keys, results.Records), nil
}View on GitHub (pinned to 8cc6e09de2)
Solutions
- Run the query without dry-run to confirm it executes and returns results.
- Inspect the raw plan returned by EXPLAIN directly against the server to see its shape.
- Upgrade/align the server and driver versions so plan fields match what buildPlanNode expects.
- Use a different, more complex query if the statement trivially produces no operators.
Example fix
// before: degenerate plan from trivial statement dryRun: true, query: "RETURN 1" // after: dry-run a statement with real operators dryRun: true, query: "MATCH (n:Person) RETURN n LIMIT 10"
Defensive patterns
Strategy: fallback
Try / catch
node, incomplete, operatorCount := buildPlanNode(plan)
if operatorCount == 0 {
// plan is empty — fall back to executing the query or returning raw plan data
return executeWithoutDryRun(ctx, cypher)
} Prevention
- Avoid dry-running trivial statements (e.g. RETURN 1) that plan to zero operators.
- Handle empty-plan responses as a distinct code path in clients of the tool.
- Upgrade server/driver versions if plan operator fields stop being populated.
- Validate plan output shape after any version bump of the database or driver.
When it happens
Trigger: Calling RunCypher with dryRun=true when the returned EXPLAIN plan has no operator nodes recognizable by buildPlanNode — an empty or degenerate plan from the server.
Common situations: Queries the backend plans as a no-op; protocol quirks producing plan objects with no children/arguments; compatibility mismatches where plan operator fields use unexpected keys.
Related errors
- dry-run produced no execution plan
- UNSUPPORTED_PROTOCOL_VERSION
- unable to create driver: %w
- unable to connect successfully: %w
- this tool is read-only and cannot execute write queries
AI-assisted analysis of googleapis/mcp-toolbox@8cc6e09de2 (2026-09-05).
Data as JSON: /api/errors/0a8ca8fbefe41de6.
Report an issue: GitHub.