apache/iceberg · error · UnsupportedOperationException

Delete files are currently not supported in changelog scans

Error message

Delete files are currently not supported in changelog scans

What it means

BaseIncrementalChangelogScan computes a row-level changelog from ancestor snapshots, but snapshots containing delete files (v2 positional/equality deletes) cannot yet produce correct changelog rows. The scan proactively fails with UnsupportedOperationException rather than emitting incomplete changelog data.

Source

Thrown at core/src/main/java/org/apache/iceberg/BaseIncrementalChangelogScan.java:109

    return manifestGroup.plan(new CreateDataFileChangeTasks(changelogSnapshots));
  }

  @Override
  public CloseableIterable<ScanTaskGroup<ChangelogScanTask>> planTasks() {
    return TableScanUtil.planTaskGroups(
        planFiles(), targetSplitSize(), splitLookback(), splitOpenFileCost());
  }

  // builds a collection of changelog snapshots (oldest to newest)
  // the order of the snapshots is important as it is used to determine change ordinals
  private Deque<Snapshot> orderedChangelogSnapshots(Long fromIdExcl, long toIdIncl) {
    Deque<Snapshot> changelogSnapshots = new ArrayDeque<>();

    for (Snapshot snapshot : SnapshotUtil.ancestorsBetween(table(), toIdIncl, fromIdExcl)) {
      if (!snapshot.operation().equals(DataOperations.REPLACE)) {
        if (!snapshot.deleteManifests(table().io()).isEmpty()) {
          throw new UnsupportedOperationException(
              "Delete files are currently not supported in changelog scans");
        }

        changelogSnapshots.addFirst(snapshot);
      }
    }

    return changelogSnapshots;
  }

  private Set<Long> toSnapshotIds(Collection<Snapshot> snapshots) {
    return snapshots.stream().map(Snapshot::snapshotId).collect(Collectors.toSet());
  }

  private static Map<Long, Integer> computeSnapshotOrdinals(Deque<Snapshot> snapshots) {
    Map<Long, Integer> snapshotOrdinals = Maps.newHashMap();

    int ordinal = 0;

View on GitHub (pinned to 86d9c8fc54)

Solutions

  1. Avoid delete operations on tables you need changelog scans over, or write changes as data files only
  2. Recreate the table/changelog via rewrite operations that emit data files instead of delete files
  3. Wait for/upgrade to a library version that supports delete files in changelog scans

Example fix

// before
CloseableIterator<ChangelogContent> it = table.createChangelogScan().appendsAfter(startId).iterator();
// after
if (hasDeleteSnapshots(table, startId)) {
  throw new IllegalStateException("Changelog scan unavailable: table snapshots contain delete files");
}
CloseableIterator<ChangelogContent> it = table.createChangelogScan().appendsAfter(startId).iterator();
Defensive patterns

Strategy: try-catch

Validate before calling

boolean hasDeletes = SnapshotUtil.ancestorsBetween(table, toId, fromId).stream()
    .anyMatch(s -> !s.deleteManifests(table.io()).isEmpty());

Try / catch

try (CloseableIterator<...> it = scan.iterator()) { ... } catch (UnsupportedOperationException e) { logger.warn("Changelog unsupported: delete files present"); fallbackToFullScan(); }

Prevention

When it happens

Trigger: table.createChangelogScan().appendsBetween(...)/useSnapshots(...) on a table where any ancestor snapshot between the boundaries has delete manifests — i.e. any MERGE/UPDATE/DELETE producing delete files.

Common situations: v2 format tables using copy-on-write or merge-on-read deletes; users upgrading from append-only workloads to delete workloads and then running changelog scans.

Understand the failure class

Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.

Related errors


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