apache/iceberg · error · UnsupportedOperationException
Deleted rows scan task is not supported yet
Error message
Deleted rows scan task is not supported yet
What it means
ChangelogRowReader.openChangelogScanTask dispatches incremental changelog scan tasks by type. AddedRowsScanTask and DeletedDataFileScanTask are supported, but DeletedRowsScanTask (position-delete-based row deletions carrying prior-row values) has no reader implementation yet, so it throws UnsupportedOperationException. The changelog mode ('incremental' with deletes) cannot process such tasks.
Source
Thrown at spark/v4.1/spark/src/main/java/org/apache/iceberg/spark/source/ChangelogRowReader.java:104
return cdcRows.iterator();
}
private static InternalRow changelogMetadata(ChangelogScanTask task) {
InternalRow metadataRow = new GenericInternalRow(3);
metadataRow.update(0, UTF8String.fromString(task.operation().name()));
metadataRow.update(1, task.changeOrdinal());
metadataRow.update(2, task.commitSnapshotId());
return metadataRow;
}
private CloseableIterable<InternalRow> openChangelogScanTask(ChangelogScanTask task) {
if (task instanceof AddedRowsScanTask) {
return openAddedRowsScanTask((AddedRowsScanTask) task);
} else if (task instanceof DeletedRowsScanTask) {
throw new UnsupportedOperationException("Deleted rows scan task is not supported yet");
} else if (task instanceof DeletedDataFileScanTask) {
return openDeletedDataFileScanTask((DeletedDataFileScanTask) task);
} else {
throw new IllegalArgumentException(
"Unsupported changelog scan task type: " + task.getClass().getName());
}
}
CloseableIterable<InternalRow> openAddedRowsScanTask(AddedRowsScanTask task) {
String filePath = task.file().location();
SparkDeleteFilter deletes = new SparkDeleteFilter(filePath, task.deletes(), counter(), true);
return deletes.filter(rows(task, deletes.requiredSchema()));
}
private CloseableIterable<InternalRow> openDeletedDataFileScanTask(DeletedDataFileScanTask task) {
String filePath = task.file().location();View on GitHub (pinned to 86d9c8fc54)
Solutions
- Avoid position deletes on the table: enable copy-on-write (write.delete.mode=copy-on-write / write.merge.mode=copy-on-write) so deletions produce deleted data files instead.
- Use a scan mode that does not need to emit prior row values for position deletes, or periodic full re-reads instead of incremental changelog.
- Upgrade Iceberg — newer releases may have implemented DeletedRowsScanTask handling.
- Run frequent rewrites/compaction to remove delete files before the changelog window.
Example fix
// before (table properties) "write.delete.mode": "merge-on-read" // after "write.delete.mode": "copy-on-write"
Defensive patterns
Strategy: validation
Validate before calling
// detect position-delete usage before enabling changelog reads
boolean usesPositionDeletes = spark.read.format("iceberg")
.load(table + ".files").filter($"content" === 2).count() > 0;
if (usesPositionDeletes) { /* reconfigure writers or avoid changelog mode */ } Try / catch
try {
spark.readStream.format("iceberg").option("stream-from-timestamp", ts).load(table);
} catch (UnsupportedOperationException e) {
if (e.getMessage().contains("Deleted rows scan task")) { /* switch to copy-on-write or full re-read */ }
} Prevention
- Set write.delete.mode/write.merge.mode to copy-on-write on tables consumed via changelog streaming
- Compact regularly to clear residual delete files before the incremental window
- Check Iceberg release notes for DeletedRowsScanTask support before upgrading readers
- Prefer equality-delete-aware Flink/Spark changelog paths where supported
When it happens
Trigger: Streaming/incremental read with read.changelog or scan.mode=incremental-append... when the computed task set contains a DeletedRowsScanTask — i.e. rows removed via v2 position deletes (merge-on-read delete files) between the start and end snapshot.
Common situations: Enabling changelog reads on tables where writers emit position deletes (Spark MERGE/DELETE with copy-on-write off, Flink upsert writes); forgetting that only equality/position delete handling for DeletedDataFile tasks is implemented; running an older Iceberg version where support is narrower.
Related errors
- Deleted rows scan task is not supported yet
- Unsupported changelog scan task type: ${task.getClass().getN
- Deleted rows scan task is not supported yet
- Unsupported changelog scan task type: ${task.getClass().getN
- Failed to close changelog scan: ${scan}
AI-assisted analysis of apache/iceberg@86d9c8fc54 (2026-09-12).
Data as JSON: /api/errors/7275e5be3d0aafab.
Report an issue: GitHub.