apache/iceberg · error · UncheckedIOException

Failed to close scan: ${scan}

Error message

Failed to close scan: ${scan}

What it means

SparkPartitioningAwareScan.tasks() plans tasks and closes the scan with CloseableIterable; if closing the planned scan throws IOException, it is wrapped in UncheckedIOException with the scan's description. This signals leaked/planning resources (file handles, manifest readers) could not be released after task planning.

Source

Thrown at spark/v4.2/spark/src/main/java/org/apache/iceberg/spark/source/SparkPartitioningAwareScan.java:197

  protected synchronized List<T> tasks() {
    if (tasks == null) {
      try (CloseableIterable<? extends ScanTask> taskIterable = scan.planFiles()) {
        List<T> plannedTasks = Lists.newArrayList();

        for (ScanTask task : taskIterable) {
          ValidationException.check(
              taskJavaClass().isInstance(task),
              "Unsupported task type, expected a subtype of %s: %s",
              taskJavaClass().getName(),
              task.getClass().getName());

          plannedTasks.add(taskJavaClass().cast(task));
        }

        this.tasks = plannedTasks;
      } catch (IOException e) {
        throw new UncheckedIOException("Failed to close scan: " + scan, e);
      }
    }

    return tasks;
  }

  @Override
  protected synchronized List<ScanTaskGroup<T>> taskGroups() {
    if (taskGroups == null) {
      if (groupingKeyType().fields().isEmpty()) {
        CloseableIterable<ScanTaskGroup<T>> plannedTaskGroups =
            TableScanUtil.planTaskGroups(
                CloseableIterable.withNoopClose(tasks()),
                adjustSplitSize(tasks(), scan.targetSplitSize()),
                scan.splitLookback(),
                scan.splitOpenFileCost());
        this.taskGroups = Lists.newArrayList(plannedTaskGroups);

View on GitHub (pinned to 86d9c8fc54)

Solutions

  1. Check the chained IOException cause for the underlying FileIO/close error and address it (network, permissions, custom FileIO bug)
  2. Raise the process file-descriptor limit (ulimit) if fd exhaustion is reported
  3. Use a well-tested FileIO implementation (HadoopFileIO / S3FileIO) instead of custom ones and retry the scan
Defensive patterns

Strategy: retry

Try / catch

try {
  tasks = scan.tasks();
} catch (UncheckedIOException e) {
  LOG.warn("Scan close failed, retrying", e.getCause());
  tasks = scan.tasks();
}

Prevention

When it happens

Trigger: task planning completes but closing the CloseableIterable of tasks throws IOException — typically an underlying FileIO error while closing manifest readers or input streams during plan() cleanup.

Common situations: Filesystem or object-store connectivity errors during close (S3 timeouts, HDFS client errors); exhausted file descriptors causing close failures; buggy custom FileIO implementations that throw on close().

Understand the failure class

Background: "failed to read file", EACCES, ENOENT and "could not read <path>" errors: when a program can't read a file from disk — this error's family across 49 libraries.

Related errors


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