{"record":{"id":"f5c8bc6090340363","repo":"apache/iceberg","slug":"cannot-read-files-that-require-applying-delete-fil","errorCode":null,"errorMessage":"Cannot read files that require applying delete files","messagePattern":"Cannot read files that require applying delete files","errorType":"exception","errorClass":"UnsupportedOperationException","httpStatus":null,"severity":"error","filePath":"arrow/src/main/java/org/apache/iceberg/arrow/vectorized/ArrowReader.java","lineNumber":241,"sourceCode":"     */\n    VectorizedCombinedScanIterator(\n        CloseableIterable<CombinedScanTask> tasks,\n        Schema expectedSchema,\n        String nameMapping,\n        FileIO io,\n        EncryptionManager encryptionManager,\n        boolean caseSensitive,\n        int batchSize,\n        boolean reuseContainers) {\n      List<FileScanTask> fileTasks =\n          StreamSupport.stream(tasks.spliterator(), false)\n              .map(CombinedScanTask::files)\n              .flatMap(Collection::stream)\n              .collect(Collectors.toList());\n      this.fileItr = fileTasks.iterator();\n\n      if (fileTasks.stream().anyMatch(TableScanUtil::hasDeletes)) {\n        throw new UnsupportedOperationException(\n            \"Cannot read files that require applying delete files\");\n      }\n\n      if (expectedSchema.columns().isEmpty()) {\n        throw new UnsupportedOperationException(\n            \"Cannot read without at least one projected column\");\n      }\n\n      Set<TypeID> unsupportedTypes =\n          Sets.difference(\n              expectedSchema.columns().stream()\n                  .map(c -> c.type().typeId())\n                  .collect(Collectors.toSet()),\n              SUPPORTED_TYPES);\n      if (!unsupportedTypes.isEmpty()) {\n        throw new UnsupportedOperationException(\n            \"Cannot read unsupported column types: \" + unsupportedTypes);\n      }","sourceCodeStart":223,"sourceCodeEnd":259,"githubUrl":"https://github.com/apache/iceberg/blob/86d9c8fc543e7c56c9f624eb725f76c9baff9570/arrow/src/main/java/org/apache/iceberg/arrow/vectorized/ArrowReader.java#L223-L259","documentation":"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.","triggerScenarios":"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).","commonSituations":"Reading a table that has had row-level deletes applied with vectorized Arrow reads enabled; Spark-less Arrow consumers scanning CDC-heavy tables.","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."],"exampleFix":null,"handlingStrategy":"validation","validationCode":"if (task.files().stream().anyMatch(TableScanUtil::hasDeletes)) { /* use non-vectorized reader */ }","typeGuard":"static boolean isVectorizable(CombinedScanTask t) { return t.files().stream().noneMatch(TableScanUtil::hasDeletes); }","tryCatchPattern":"try { return new VectorizedCombinedScanIterator(...); } catch (UnsupportedOperationException e) { return nonVectorizedIterator(...); }","preventionTips":["Check TableScanUtil.hasDeletes before choosing the vectorized reader","Compact/rewrite tables to remove delete files before Arrow scans"],"tags":["java","arrow","vectorized-read","delete-files"],"backgroundTag":"feature-not-enabled","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"}