{"record":{"id":"60218884dcdfd552","repo":"apache/iceberg","slug":"not-implemented-copy-602188","errorCode":null,"errorMessage":"Not implemented: copy","messagePattern":"Not implemented: copy","errorType":"exception","errorClass":"UnsupportedOperationException","httpStatus":null,"severity":"error","filePath":"spark/v4.0/spark/src/main/java/org/apache/iceberg/spark/SparkContentFile.java","lineNumber":217,"sourceCode":"        wrapped.isNullAt(lowerBoundsPosition) ? null : wrapped.getJavaMap(lowerBoundsPosition);\n    return convert(lowerBoundsType, lowerBounds);\n  }\n\n  @Override\n  public Map<Integer, ByteBuffer> upperBounds() {\n    Map<?, ?> upperBounds =\n        wrapped.isNullAt(upperBoundsPosition) ? null : wrapped.getJavaMap(upperBoundsPosition);\n    return convert(upperBoundsType, upperBounds);\n  }\n\n  @Override\n  public ByteBuffer keyMetadata() {\n    return convert(keyMetadataType, wrapped.get(keyMetadataPosition));\n  }\n\n  @Override\n  public F copy() {\n    throw new UnsupportedOperationException(\"Not implemented: copy\");\n  }\n\n  @Override\n  public F copyWithoutStats() {\n    throw new UnsupportedOperationException(\"Not implemented: copyWithoutStats\");\n  }\n\n  @Override\n  public List<Long> splitOffsets() {\n    return wrapped.isNullAt(splitOffsetsPosition) ? null : wrapped.getList(splitOffsetsPosition);\n  }\n\n  @Override\n  public Integer sortOrderId() {\n    return wrapped.getAs(sortOrderIdPosition);\n  }\n\n  @Override","sourceCodeStart":199,"sourceCodeEnd":235,"githubUrl":"https://github.com/apache/iceberg/blob/86d9c8fc543e7c56c9f624eb725f76c9baff9570/spark/v4.0/spark/src/main/java/org/apache/iceberg/spark/SparkContentFile.java#L199-L235","documentation":"SparkContentFile wraps a Spark InternalRow as a ContentFile and does not implement copy(). Copying requires constructing a fully independent file object with its own stats, which this wrapper deliberately does not support since it delegates to a shared row. Any code path that calls copy() on a Spark-backed ContentFile hits this UnsupportedOperationException.","triggerScenarios":"Calling copy() on a SparkContentFile/SparkDeleteFile instance, e.g. when a scan or delete-processing API requires an owned copy of the file record rather than a live view over the row.","commonSituations":"Custom delete-file processing or scan planning code that reuses Iceberg patterns like copyWithoutStats on Spark wrapper objects; engine integration code assuming all ContentFile implementations support copy.","solutions":["Convert to a core DataFile/DeleteFile (e.g. via GenericDataFile builders) before copying.","Restructure code so the underlying row is read in place instead of copying.","If in your own catalog code, implement copy() by building a new instance from the wrapped row's fields."],"exampleFix":"// before\nContentFile<?> owned = sparkFile.copy(); // throws\n// after\nDataFile owned = new GenericDataFile(\n    sparkFile.location(), sparkFile.partition(), sparkFile.recordCount(),\n    sparkFile.fileSizeInBytes(), sparkFile.fileOffsetInBytes(), sparkFile.rowPositions());","handlingStrategy":"fallback","validationCode":null,"typeGuard":"boolean supportsCopy(org.apache.iceberg.ContentFile<?> f) {\n  return !(f instanceof org.apache.iceberg.spark.SparkContentFile);\n}","tryCatchPattern":"try {\n  owned = file.copy();\n} catch (UnsupportedOperationException e) {\n  owned = buildGenericDataFile(file); // convert wrapper to core file first\n}","preventionTips":["Convert Spark wrappers to GenericDataFile before calling copy APIs.","Avoid storing SparkContentFile references in code that expects owned copies.","Review Iceberg scan/delete APIs for copy requirements before integration."],"tags":["spark","datafile","unsupported-operation"],"backgroundTag":"method-not-implemented","analyzedSha":"86d9c8fc543e7c56c9f624eb725f76c9baff9570","analyzedAt":"2026-09-12T00:46:39.097Z","contentChangedAt":"2026-09-12T00:46:39.097Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}