apache/iceberg · error · RuntimeException
Failed to plan files
Error message
Failed to plan files
What it means
BaseDistributedDataScan.doPlanFiles() throws RuntimeException('Failed to plan files') when a CompletionException escapes the coordinated planning of data and delete futures (e.g. a remote scan task failed or was cancelled). The two futures are cancelled and the underlying exception is attached as the cause. It wraps whatever failure occurred during distributed scan planning.
Solutions
- Inspect e.getCause() (the CompletionException cause) for the root failure
- Retry the scan planning; transient executor/storage failures may recover
- Increase executor thread pool size or timeout budgets for remote planning
- Fall back to local planning by tuning planning-mode properties (see shouldPlanLocally)
- Check task executor logs in the distributed environment for the original stack
Example fix
// before
CloseableIterable<FileScanTask> tasks = distributedScan.planFiles(); // RuntimeException on remote failure
// after
try {
tasks = distributedScan.planFiles();
} catch (RuntimeException e) {
Throwable root = e.getCause() == null ? e : e.getCause();
LOG.error("Planning failed: {}", root.getMessage(), root);
tasks = table.newScan().planFiles(); // fall back to local planning
} Defensive patterns
Strategy: try-catch
Validate before calling
null
Type guard
null
Try / catch
try { tasks = scan.planFiles(); } catch (RuntimeException e) { Throwable cause = e.getCause(); /* CompletionException cause has the root failure */ } Prevention
- Monitor remote planning executor health and timeouts
- Log and inspect getCause() for root-cause triage
- Tune planning mode so remote planning is used only when beneficial
- Add retry with backoff around scan planning
When it happens
Trigger: The dataFiles or deletes CompletableFuture completes exceptionally (task executor failure, remote manifest read error, cancellation) while joining results in doPlanFiles.
Common situations: Executor thread death or OOM in a distributed planner; timeouts reading manifests remotely; shutdown of the monitoring pool mid-plan.
Understand the failure class
Background: 'Something went wrong' / 'Request failed (500)' / 'HTTP error! status: 404' — what failed HTTP requests actually mean and how to find the real cause — this error's family across 28 libraries.
Related errors
- Can't handle
- Cannot call acquireLock twice for
- Cannot commit: Base metadata location
- Cannot commit changes based on stale table metadata
- Cannot commit file that conflicts with existing partition
AI-assisted analysis of apache/iceberg@86d9c8fc54 (2026-09-12).
Data as JSON: /api/errors/7fc6f68553cd00da.
Report an issue: GitHub.
Appendix: source
Thrown at core/src/main/java/org/apache/iceberg/BaseDistributedDataScan.java:183
newDeletesFuture(deleteManifests, planDeletesLocally, monitorPool);
CompletableFuture<Iterable<CloseableIterable<DataFile>>> dataFuture =
newDataFuture(dataManifests, planDataLocally, loadColumnStats, monitorPool);
try {
Iterable<CloseableIterable<ScanTask>> fileTasks =
toFileTasks(dataFuture, deletesFuture, copyDataFiles);
if (shouldPlanWithExecutor() && (planDataLocally || mayHaveEqualityDeletes)) {
return new ParallelIterable<>(fileTasks, planExecutor());
} else {
return CloseableIterable.concat(fileTasks);
}
} catch (CompletionException e) {
deletesFuture.cancel(true /* may interrupt */);
dataFuture.cancel(true /* may interrupt */);
throw new RuntimeException("Failed to plan files", e);
} finally {
monitorPool.shutdown();
}
}
@Override
public CloseableIterable<ScanTaskGroup<ScanTask>> planTasks() {
return TableScanUtil.planTaskGroups(
planFiles(), targetSplitSize(), splitLookback(), splitOpenFileCost());
}
private List<ManifestFile> findMatchingDataManifests(Snapshot snapshot) {
List<ManifestFile> dataManifests = snapshot.dataManifests(table().io());
scanMetrics().totalDataManifests().increment(dataManifests.size());
List<ManifestFile> matchingDataManifests = filterManifests(dataManifests);
int skippedDataManifestsCount = dataManifests.size() - matchingDataManifests.size();View on GitHub (pinned to 86d9c8fc54)