apache/iceberg · error · UnsupportedOperationException
Cannot read files that require applying delete files
Error message
Cannot read files that require applying delete files
What it means
ArrowReader's VectorizedCombinedScanIterator eagerly checks every FileScanTask in the CombinedScanTask with TableScanUtil.hasDeletes. If any task requires applying delete files, the vectorized reader throws this UnsupportedOperationException because delete application is not supported on the Arrow read path.
Source
Thrown at arrow/src/main/java/org/apache/iceberg/arrow/vectorized/ArrowReader.java:241
*/
VectorizedCombinedScanIterator(
CloseableIterable<CombinedScanTask> tasks,
Schema expectedSchema,
String nameMapping,
FileIO io,
EncryptionManager encryptionManager,
boolean caseSensitive,
int batchSize,
boolean reuseContainers) {
List<FileScanTask> fileTasks =
StreamSupport.stream(tasks.spliterator(), false)
.map(CombinedScanTask::files)
.flatMap(Collection::stream)
.collect(Collectors.toList());
this.fileItr = fileTasks.iterator();
if (fileTasks.stream().anyMatch(TableScanUtil::hasDeletes)) {
throw new UnsupportedOperationException(
"Cannot read files that require applying delete files");
}
if (expectedSchema.columns().isEmpty()) {
throw new UnsupportedOperationException(
"Cannot read without at least one projected column");
}
Set<TypeID> unsupportedTypes =
Sets.difference(
expectedSchema.columns().stream()
.map(c -> c.type().typeId())
.collect(Collectors.toSet()),
SUPPORTED_TYPES);
if (!unsupportedTypes.isEmpty()) {
throw new UnsupportedOperationException(
"Cannot read unsupported column types: " + unsupportedTypes);
}View on GitHub (pinned to 86d9c8fc54)
Solutions
- Rewrite/compact the table (e.g. rewrite_data_files / expire or apply deletes) so no delete files remain for the scanned snapshots.
- Fall back to the regular (row-based) record reader that supports delete application instead of the Arrow reader.
- Filter the scan to a snapshot before deletes were introduced if acceptable.
Defensive patterns
Strategy: validation
Validate before calling
if (task.files().stream().anyMatch(TableScanUtil::hasDeletes)) { /* use non-vectorized reader */ } Type guard
static boolean isVectorizable(CombinedScanTask t) { return t.files().stream().noneMatch(TableScanUtil::hasDeletes); } Try / catch
try { return new VectorizedCombinedScanIterator(...); } catch (UnsupportedOperationException e) { return nonVectorizedIterator(...); } Prevention
- Check TableScanUtil.hasDeletes before choosing the vectorized reader
- Compact/rewrite tables to remove delete files before Arrow scans
When it happens
Trigger: Opening a VectorizedCombinedScanIterator (IcebergArrowReader) over a scan task containing equality- or position-delete files (e.g. a table with v2 delete files from MERGE/UPDATE operations).
Common situations: Reading a table that has had row-level deletes applied with vectorized Arrow reads enabled; Spark-less Arrow consumers scanning CDC-heavy tables.
Related errors
- Cannot read without at least one projected column
- Unsupported primitive type:
- Cannot convert dict encoded field '%s' of type '%s' to Arrow
- Cannot read unsupported column types:
- Format: not supported for batched reads
AI-assisted analysis of apache/iceberg@86d9c8fc54 (2026-09-12).
Data as JSON: /api/errors/f5c8bc6090340363.
Report an issue: GitHub.