{"record":{"id":"0a8ca8fbefe41de6","repo":"googleapis/mcp-toolbox","slug":"dry-run-produced-an-empty-execution-plan","errorCode":null,"errorMessage":"dry-run produced an empty execution plan","messagePattern":"dry-run produced an empty execution plan","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/sources/arcadedb/arcadedb.go","lineNumber":156,"sourceCode":"\t}\n\n\tconfig := neo4j.ExecuteQueryWithDatabase(s.ArcadeDBDatabase())\n\tresults, err := neo4j.ExecuteQuery[*neo4j.EagerResult](ctx, s.ArcadeDBDriver(), cypherStr, params,\n\t\tneo4j.EagerResultTransformer, config)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"unable to execute query: %w\", err)\n\t}\n\n\tif dryRun {\n\t\tsummary := results.Summary\n\t\tplan := summary.Plan()\n\t\tif plan == nil {\n\t\t\treturn nil, fmt.Errorf(\"dry-run produced no execution plan\")\n\t\t}\n\n\t\tnode, incomplete, operatorCount := buildPlanNode(plan)\n\t\tif operatorCount == 0 {\n\t\t\treturn nil, fmt.Errorf(\"dry-run produced an empty execution plan\")\n\t\t}\n\n\t\texecPlan := map[string]any{\n\t\t\t\"queryType\":     cf.Type.String(),\n\t\t\t\"statementType\": summary.QueryType(),\n\t\t}\n\t\tfor k, v := range node {\n\t\t\texecPlan[k] = v\n\t\t}\n\t\tif incomplete {\n\t\t\texecPlan[\"plan_incomplete\"] = true\n\t\t\texecPlan[\"warning\"] = \"Execution plan appears partial; server may not provide complete EXPLAIN details for this query/version.\"\n\t\t}\n\t\treturn []map[string]any{execPlan}, nil\n\t}\n\n\treturn formatRecords(results.Keys, results.Records), nil\n}","sourceCodeStart":138,"sourceCodeEnd":174,"githubUrl":"https://github.com/googleapis/mcp-toolbox/blob/8cc6e09de2ad7b8bffc77751799585a1401a48eb/internal/sources/arcadedb/arcadedb.go#L138-L174","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before: degenerate plan from trivial statement\ndryRun: true, query: \"RETURN 1\"\n// after: dry-run a statement with real operators\ndryRun: true, query: \"MATCH (n:Person) RETURN n LIMIT 10\"","handlingStrategy":"fallback","validationCode":null,"typeGuard":null,"tryCatchPattern":"node, incomplete, operatorCount := buildPlanNode(plan)\nif operatorCount == 0 {\n    // plan is empty — fall back to executing the query or returning raw plan data\n    return executeWithoutDryRun(ctx, cypher)\n}","preventionTips":["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."],"tags":["arcadedb","dry-run","execution-plan","compatibility"],"backgroundTag":"empty-execution-plan","analyzedSha":"8cc6e09de2ad7b8bffc77751799585a1401a48eb","analyzedAt":"2026-09-05T01:10:36.887Z","contentChangedAt":"2026-09-05T01:10:36.887Z","schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}