apache/iceberg · error · NoSuchPlanIdException

Could not find plan ID

Error message

Could not find plan ID %s

What it means

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.

Solutions

  1. Confirm the planId matches the one returned by plan submission
  2. Ensure the plan has registered initial tasks (sequence number 0) before fetching
  3. Re-plan the scan against the current server instance if state was reset
  4. Check task-key construction so initial tasks carry the expected sequence number suffix

Example fix

// before
Pair<List<FileScanTask>, String> initial = state.initialScanTasksFor(guessedPlanId);
// after
String planId = submitPlan(request); // returns registered id
Pair<List<FileScanTask>, String> initial = state.initialScanTasksFor(planId);
Defensive patterns

Strategy: try-catch

Validate before calling

if (planId == null) throw new IllegalArgumentException("planId required before fetching initial tasks");

Try / catch

try {
  Pair<List<FileScanTask>, String> initial = planningState.initialScanTasksFor(planId);
} catch (NoSuchPlanIdException e) {
  // plan unknown: re-submit the planning request
}

Prevention

When it happens

Trigger: 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.

Common situations: Client fetches initial tasks before plan submission completes; restart of the in-memory test server wiped registered tasks; wrong planId passed from the client.

Understand the failure class

Background: 'Could not be found', 'does not exist', 'not found in database': the resource-not-found family when an ID, slug, key, or URI lookup comes back empty — this error's family across 20 libraries.

Related errors


AI-assisted analysis of apache/iceberg@86d9c8fc54 (2026-09-12). Data as JSON: /api/errors/b2e4e6e1ba5872ca. Report an issue: GitHub.

Appendix: source

Thrown at core/src/main/java/org/apache/iceberg/rest/InMemoryPlanningState.java:157

    Set<Map.Entry<String, List<FileScanTask>>> matchingEntries =
        planTaskToFileScanTasks.entrySet().stream()
            .filter(
                entry -> {
                  String key = entry.getKey();
                  if (!key.contains(planId)) {
                    return false;
                  }
                  List<String> keyParts = Splitter.on("-").splitToList(key);
                  if (keyParts.isEmpty()) {
                    return false;
                  }

                  return INITIAL_TASK_SEQUENCE_NUMBER.equals(keyParts.get(keyParts.size() - 1));
                })
            .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue))
            .entrySet();
    if (matchingEntries.isEmpty()) {
      throw new NoSuchPlanIdException("Could not find plan ID %s", planId);
    }

    Map.Entry<String, List<FileScanTask>> initialEntry = Iterables.getOnlyElement(matchingEntries);
    return Pair.of(initialEntry.getValue(), initialEntry.getKey());
  }

  void cancelPlan(String planId) {
    planTaskToNext.entrySet().removeIf(entry -> entry.getKey().contains(planId));
    planTaskToFileScanTasks.entrySet().removeIf(entry -> entry.getKey().contains(planId));
    // Clear the ongoing plan status in case the planID is an async one.
    if (asyncPlanningStates.containsKey(planId)) {
      PlanStatus existingStatus = asyncPlanningStates.get(planId);
      // No need to fail cancellation if the plan could not be found
      if (existingStatus == null) {
        return;
      }

      // No need to fail cancellation if the plan already terminated

View on GitHub (pinned to 86d9c8fc54)