{"record":{"id":"c1dc36b244d7babe","repo":"apache/iceberg","slug":"remove-is-not-supported-c1dc36","errorCode":null,"errorMessage":"Remove is not supported","messagePattern":"Remove is not supported","errorType":"exception","errorClass":"UnsupportedOperationException","httpStatus":null,"severity":"error","filePath":"spark/v3.5/spark/src/main/java/org/apache/iceberg/spark/source/DVIterator.java","lineNumber":104,"sourceCode":"          rowValues.add(ScanTaskUtil.contentSizeInBytes(deleteFile));\n        } else if (fieldId == MetadataColumns.DELETE_FILE_ROW_FIELD_ID) {\n          // DVs don't track the row that was deleted\n          rowValues.add(null);\n        }\n      }\n\n      this.row = new GenericInternalRow(rowValues.toArray());\n    } else if (null != deletedPositionIndex) {\n      // only update the deleted position if necessary, everything else stays the same\n      row.update(deletedPositionIndex, position);\n    }\n\n    return row;\n  }\n\n  @Override\n  public void remove() {\n    throw new UnsupportedOperationException(\"Remove is not supported\");\n  }\n\n  @Override\n  public void close() {}\n}\n","sourceCodeStart":86,"sourceCodeEnd":110,"githubUrl":"https://github.com/apache/iceberg/blob/86d9c8fc543e7c56c9f624eb725f76c9baff9570/spark/v3.5/spark/src/main/java/org/apache/iceberg/spark/source/DVIterator.java#L86-L110","documentation":"DVIterator implements Java's legacy Iterator interface, whose remove() default operation is unsupported. Iceberg's iterator over rows feeding deletion-vector writes is read-only, so any call to remove() fails fast rather than corrupting state. This is a deliberate guard: removal is meaningless for a scan-backed stream.","triggerScenarios":"Calling remove() on the Iterator returned by DVIterator, e.g. code that iterates rows and mutates the underlying collection via iterator.remove().","commonSituations":"Legacy Java code or third-party utilities that use Iterator.remove() while draining scan results passed into deletion-vector-producing readers.","solutions":["Do not call remove(); iterate read-only and collect the rows you need.","If filtering is required, filter upstream in the scan/plan instead of mutating during iteration.","Use CloseableIterable.filter for filtered views instead of Iterator.remove."],"exampleFix":"// before\nwhile (it.hasNext()) {\n  Row r = it.next();\n  if (!keep(r)) { it.remove(); } // throws\n}\n// after\nCloseableIterable<Row> kept = CloseableIterable.filter(rows, this::keep);","handlingStrategy":"type-guard","validationCode":null,"typeGuard":"if (iterator instanceof DVIterator) { /* never call remove(); treat as read-only */ }","tryCatchPattern":null,"preventionTips":["Treat all Iceberg scan iterators as read-only","Never use Iterator.remove() on data returned from Iceberg scans","Prefer CloseableIterable.filter/combiner over mutation during iteration"],"tags":["spark","iterator","read-only","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"}