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

  1. Route insert rows to the data-side BatchWrite/RowDataWriter, not the position-delete delegate
  2. Use Iceberg's standard MERGE/append paths so Spark plans insert branches against the data writer
  3. 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

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


AI-assisted analysis of apache/iceberg@86d9c8fc54 (2026-09-12). Data as JSON: /api/errors/50157dedbe2ee72e. Report an issue: GitHub.