googleapis/mcp-toolbox · error

dry-run produced no execution plan

Error message

dry-run produced no execution plan

What it means

In dry-run mode, RunCypher prefixes the query with EXPLAIN and expects the result summary to contain an execution plan. This error means the server returned a summary whose Plan() is nil — no plan object was produced — so the dry-run contract cannot be honored. It indicates the server did not return plan metadata for the EXPLAIN query.

Source

Thrown at internal/sources/arcadedb/arcadedb.go:151

		return nil, fmt.Errorf("this tool is read-only and cannot execute write queries")
	}

	if dryRun {
		cypherStr = "EXPLAIN " + cypherStr
	}

	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."
		}

View on GitHub (pinned to 8cc6e09de2)

Solutions

  1. Retry without dry-run to execute the query normally.
  2. Upgrade the ArcadeDB server to a version whose Bolt layer returns EXPLAIN plans for this query type.
  3. Check that the query type is one the backend supports explaining (avoid utility/management statements).
  4. Verify driver/server protocol compatibility (neo4j Go driver version vs ArcadeDB Bolt version).

Example fix

// before
dryRun: true, query: "CALL db.labels()"
// after: execute directly if the backend cannot explain it
dryRun: false, query: "CALL db.labels()"
Defensive patterns

Strategy: fallback

Try / catch

plan := results.Summary.Plan()
if plan == nil {
    // fall back to executing the query without dry-run, or surface a clear message
    return executeWithoutDryRun(ctx, cypher)
}

Prevention

When it happens

Trigger: Calling RunCypher with dryRun=true when the backend (ArcadeDB via the Neo4j-compatible Bolt layer) returns a summary without a plan, e.g. the EXPLAIN prefix is unsupported for that statement type or the server omits plan data.

Common situations: Using dry-run against an ArcadeDB version or query type that doesn't emit plan summaries; statements the backend executes without planning metadata; protocol/compatibility mismatches between driver and server versions.

Related errors


AI-assisted analysis of googleapis/mcp-toolbox@8cc6e09de2 (2026-09-05). Data as JSON: /api/errors/0e2d07ccf7b6ef07. Report an issue: GitHub.