apache/iceberg · error · UnsupportedOperationException

${this.getClass().getName()} does not implement update

Error message

${this.getClass().getName()} does not implement update

What it means

The position-delta writer delegates writes as delete files plus inserts; it has no path for in-place row updates. Spark's RowDataWriter update() entry point therefore throws UnsupportedOperationException identifying the concrete writer class.

Source

Thrown at spark/v3.5/spark/src/main/java/org/apache/iceberg/spark/source/SparkPositionDeltaWrite.java:609

    @Override
    public void delete(InternalRow metadata, InternalRow id) throws IOException {
      int specId = metadata.getInt(specIdOrdinal);
      PartitionSpec spec = specs.get(specId);

      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

View on GitHub (pinned to 86d9c8fc54)

Solutions

  1. Express updates as delete+insert (this is how the writer expects them; check the Spark action generating updates).
  2. Enable copy-on-write mode for the table so updates are supported: set write.update.mode=copy-on-write.
  3. Upgrade Iceberg/Spark integration to a version whose delta writer supports update operations if available.

Example fix

// before
UPDATE catalog.db.t SET c = 1 WHERE id = 5 // delta writer path
// after
ALTER TABLE catalog.db.t SET TBLPROPERTIES ('write.update.mode'='copy-on-write')
Defensive patterns

Strategy: validation

Validate before calling

// ensure updates are supported for the table's write mode
String mode = table.properties().getOrDefault("write.update.mode", "merge-on-read");
boolean updatesSupported = "copy-on-write".equals(mode);

Try / catch

try { writer.update(meta, id, row); } catch (UnsupportedOperationException e) { /* rewrite as delete+insert */ }

Prevention

When it happens

Trigger: A MERGE/position-delta write plan producing an 'update' operation (metadata + id + full row) routed to this writer, e.g. Spark emitting UPDATE rows through SparkWrite's position delta path.

Common situations: Running MERGE WHEN MATCHED THEN UPDATE (or UPDATE table) on a table configured for copy-on-write disabled / position-delta writes where the writer does not support update ops.

Related errors


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