apache/iceberg · error · UnsupportedOperationException
${this.getClass().getName()} does not implement insert
Error message
${this.getClass().getName()} does not implement insert What it means
Like update(), the insert(row) method of this position-delete delegate writer is not implemented; inserts into the data table are handled elsewhere in the delta write plan. Calling insert() throws UnsupportedOperationException identifying the concrete writer class.
Source
Thrown at spark/v4.2/spark/src/main/java/org/apache/iceberg/spark/source/SparkPositionDeltaWrite.java:653
InternalRow partition = metadata.getStruct(partitionOrdinal, partitionRowWrapper.size());
StructProjection partitionProjection = partitionProjections.get(specId);
partitionProjection.wrap(partitionRowWrapper.wrap(partition));
String file = id.getString(fileOrdinal);
long position = id.getLong(positionOrdinal);
positionDelete.set(file, position);
delegate.write(positionDelete, spec, partitionProjection);
}
@Override
public void update(InternalRow metadata, InternalRow id, InternalRow row) {
throw new UnsupportedOperationException(
this.getClass().getName() + " does not implement update");
}
@Override
public void insert(InternalRow row) throws IOException {
throw new UnsupportedOperationException(
this.getClass().getName() + " does not implement insert");
}
@Override
public WriterCommitMessage commit() throws IOException {
close();
DeleteWriteResult result = delegate.result();
return new DeltaTaskCommit(result);
}
@Override
public void abort() throws IOException {
close();
DeleteWriteResult result = delegate.result();
SparkCleanupUtil.deleteTaskFiles(io, result.deleteFiles());
}View on GitHub (pinned to 86d9c8fc54)
Solutions
- Route insert rows to the data-side BatchWrite/RowDataWriter, not the position-delete delegate
- Use Iceberg's standard MERGE/append paths so Spark plans insert branches against the data writer
- Check which RowDataWriter class is wired for each delta branch in custom integrations
Defensive patterns
Strategy: type-guard
Validate before calling
if (!(writer instanceof SupportsInsert)) {
throw new IllegalArgumentException("This writer does not accept inserts");
} Type guard
boolean acceptsInsert = !(writer instanceof PositionDeleteDelegate);
Prevention
- Send inserts to the data-side writer only
- Map each MERGE branch to the correct writer type
- Review custom delta-write wiring in integrations
When it happens
Trigger: Spark delta execution invoking insert(InternalRow) on the position-delete writer produced by SparkPositionDeltaWrite instead of on the data-table writer.
Common situations: Custom write pipelines routing insert rows to the delete writer; misconfigured write builders assigning the wrong writer for the insert side of a MERGE WHEN NOT MATCHED branch.
Related errors
- Update must be represented as delete and insert
- ${this.getClass().getName()} does not implement update
- Cannot apply unknown table change: ${change}
- SparkCachedTableCatalog does not support altering tables
- SparkCachedTableCatalog does not support dropping tables
AI-assisted analysis of apache/iceberg@86d9c8fc54 (2026-09-12).
Data as JSON: /api/errors/50157dedbe2ee72e.
Report an issue: GitHub.