{"record":{"id":"1a5e1cf125746ca0","repo":"apache/iceberg","slug":"delete-files-are-currently-not-supported-in-change","errorCode":null,"errorMessage":"Delete files are currently not supported in changelog scans","messagePattern":"Delete files are currently not supported in changelog scans","errorType":"exception","errorClass":"UnsupportedOperationException","httpStatus":null,"severity":"error","filePath":"core/src/main/java/org/apache/iceberg/BaseIncrementalChangelogScan.java","lineNumber":109,"sourceCode":"\n    return manifestGroup.plan(new CreateDataFileChangeTasks(changelogSnapshots));\n  }\n\n  @Override\n  public CloseableIterable<ScanTaskGroup<ChangelogScanTask>> planTasks() {\n    return TableScanUtil.planTaskGroups(\n        planFiles(), targetSplitSize(), splitLookback(), splitOpenFileCost());\n  }\n\n  // builds a collection of changelog snapshots (oldest to newest)\n  // the order of the snapshots is important as it is used to determine change ordinals\n  private Deque<Snapshot> orderedChangelogSnapshots(Long fromIdExcl, long toIdIncl) {\n    Deque<Snapshot> changelogSnapshots = new ArrayDeque<>();\n\n    for (Snapshot snapshot : SnapshotUtil.ancestorsBetween(table(), toIdIncl, fromIdExcl)) {\n      if (!snapshot.operation().equals(DataOperations.REPLACE)) {\n        if (!snapshot.deleteManifests(table().io()).isEmpty()) {\n          throw new UnsupportedOperationException(\n              \"Delete files are currently not supported in changelog scans\");\n        }\n\n        changelogSnapshots.addFirst(snapshot);\n      }\n    }\n\n    return changelogSnapshots;\n  }\n\n  private Set<Long> toSnapshotIds(Collection<Snapshot> snapshots) {\n    return snapshots.stream().map(Snapshot::snapshotId).collect(Collectors.toSet());\n  }\n\n  private static Map<Long, Integer> computeSnapshotOrdinals(Deque<Snapshot> snapshots) {\n    Map<Long, Integer> snapshotOrdinals = Maps.newHashMap();\n\n    int ordinal = 0;","sourceCodeStart":91,"sourceCodeEnd":127,"githubUrl":"https://github.com/apache/iceberg/blob/86d9c8fc543e7c56c9f624eb725f76c9baff9570/core/src/main/java/org/apache/iceberg/BaseIncrementalChangelogScan.java#L91-L127","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Avoid delete operations on tables you need changelog scans over, or write changes as data files only","Recreate the table/changelog via rewrite operations that emit data files instead of delete files","Wait for/upgrade to a library version that supports delete files in changelog scans"],"exampleFix":"// before\nCloseableIterator<ChangelogContent> it = table.createChangelogScan().appendsAfter(startId).iterator();\n// after\nif (hasDeleteSnapshots(table, startId)) {\n  throw new IllegalStateException(\"Changelog scan unavailable: table snapshots contain delete files\");\n}\nCloseableIterator<ChangelogContent> it = table.createChangelogScan().appendsAfter(startId).iterator();","handlingStrategy":"try-catch","validationCode":"boolean hasDeletes = SnapshotUtil.ancestorsBetween(table, toId, fromId).stream()\n    .anyMatch(s -> !s.deleteManifests(table.io()).isEmpty());","typeGuard":null,"tryCatchPattern":"try (CloseableIterator<...> it = scan.iterator()) { ... } catch (UnsupportedOperationException e) { logger.warn(\"Changelog unsupported: delete files present\"); fallbackToFullScan(); }","preventionTips":["Do not enable changelog consumers on tables that use delete files","Audit table format version and delete usage before building changelog pipelines","Track Iceberg release notes for delete-file changelog support"],"tags":["changelog","delete-files","unsupported-operation"],"backgroundTag":"unsupported-operation","analyzedSha":"86d9c8fc543e7c56c9f624eb725f76c9baff9570","analyzedAt":"2026-09-12T00:46:39.097Z","contentChangedAt":"2026-09-12T00:46:39.097Z","schemaVersion":2},"datasetVersion":"2026-09-14T16:17:12.679Z"}