{"record":{"id":"b2e4e6e1ba5872ca","repo":"apache/iceberg","slug":"could-not-find-plan-id-s","errorCode":null,"errorMessage":"Could not find plan ID %s","messagePattern":"Could not find plan ID (.+?)","errorType":"exception","errorClass":"NoSuchPlanIdException","httpStatus":404,"severity":"error","filePath":"core/src/main/java/org/apache/iceberg/rest/InMemoryPlanningState.java","lineNumber":157,"sourceCode":"    Set<Map.Entry<String, List<FileScanTask>>> matchingEntries =\n        planTaskToFileScanTasks.entrySet().stream()\n            .filter(\n                entry -> {\n                  String key = entry.getKey();\n                  if (!key.contains(planId)) {\n                    return false;\n                  }\n                  List<String> keyParts = Splitter.on(\"-\").splitToList(key);\n                  if (keyParts.isEmpty()) {\n                    return false;\n                  }\n\n                  return INITIAL_TASK_SEQUENCE_NUMBER.equals(keyParts.get(keyParts.size() - 1));\n                })\n            .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue))\n            .entrySet();\n    if (matchingEntries.isEmpty()) {\n      throw new NoSuchPlanIdException(\"Could not find plan ID %s\", planId);\n    }\n\n    Map.Entry<String, List<FileScanTask>> initialEntry = Iterables.getOnlyElement(matchingEntries);\n    return Pair.of(initialEntry.getValue(), initialEntry.getKey());\n  }\n\n  void cancelPlan(String planId) {\n    planTaskToNext.entrySet().removeIf(entry -> entry.getKey().contains(planId));\n    planTaskToFileScanTasks.entrySet().removeIf(entry -> entry.getKey().contains(planId));\n    // Clear the ongoing plan status in case the planID is an async one.\n    if (asyncPlanningStates.containsKey(planId)) {\n      PlanStatus existingStatus = asyncPlanningStates.get(planId);\n      // No need to fail cancellation if the plan could not be found\n      if (existingStatus == null) {\n        return;\n      }\n\n      // No need to fail cancellation if the plan already terminated","sourceCodeStart":139,"sourceCodeEnd":175,"githubUrl":"https://github.com/apache/iceberg/blob/86d9c8fc543e7c56c9f624eb725f76c9baff9570/core/src/main/java/org/apache/iceberg/rest/InMemoryPlanningState.java#L139-L175","documentation":"InMemoryPlanningState identifies the initial (sequence-number-0) plan tasks by parsing plan-task keys; initialScanTasksFor throws NoSuchPlanIdException when no entry matching the given planId with an initial task is found. The plan either does not exist or has no initial tasks registered under it.","triggerScenarios":"Requesting initial scan tasks for a planId that was never planned; a plan whose task keys were never registered with the initial sequence number (INITIAL_TASK_SEQUENCE_NUMBER); spelling/pluralization differences between stored and requested IDs.","commonSituations":"Client fetches initial tasks before plan submission completes; restart of the in-memory test server wiped registered tasks; wrong planId passed from the client.","solutions":["Confirm the planId matches the one returned by plan submission","Ensure the plan has registered initial tasks (sequence number 0) before fetching","Re-plan the scan against the current server instance if state was reset","Check task-key construction so initial tasks carry the expected sequence number suffix"],"exampleFix":"// before\nPair<List<FileScanTask>, String> initial = state.initialScanTasksFor(guessedPlanId);\n// after\nString planId = submitPlan(request); // returns registered id\nPair<List<FileScanTask>, String> initial = state.initialScanTasksFor(planId);","handlingStrategy":"try-catch","validationCode":"if (planId == null) throw new IllegalArgumentException(\"planId required before fetching initial tasks\");","typeGuard":null,"tryCatchPattern":"try {\n  Pair<List<FileScanTask>, String> initial = planningState.initialScanTasksFor(planId);\n} catch (NoSuchPlanIdException e) {\n  // plan unknown: re-submit the planning request\n}","preventionTips":["Derive planId exclusively from the plan submission response","Ensure initial tasks are registered under the exact planId","Do not fetch initial tasks before submission completes","Restart-aware flows must re-plan after state resets"],"tags":["rest-catalog","planning","not-found"],"backgroundTag":"resource-not-found","analyzedSha":"86d9c8fc543e7c56c9f624eb725f76c9baff9570","analyzedAt":"2026-09-12T00:46:39.097Z","contentChangedAt":"2026-09-12T00:46:39.097Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}