apache/iceberg · error · java.lang.UnsupportedOperationException

Cannot set row kind in the RowDataProjection

Error message

Cannot set row kind in the RowDataProjection

What it means

RowDataProjection wraps a projected view over another RowData and deliberately forbids mutating the row kind: setRowKind(RowKind) unconditionally throws UnsupportedOperationException. Row kind (INSERT/DELETE/UPDATE_BEFORE/UPDATE_AFTER) belongs to the underlying source row, not a projection of it.

Solutions

  1. Call setRowKind on the underlying/original RowData (the one wrapped by the projection) instead of the projection itself.
  2. Copy the projected fields into a new GenericRowData and set the RowKind on that copy.
  3. Restructure the pipeline to apply row-kind changes before projection.

Example fix

// before
projectedRow.setRowKind(RowKind.DELETE);
// after
GenericRowData out = new GenericRowData(projectedRow.getArity());
for (int i = 0; i < projectedRow.getArity(); i++) out.setField(i, RowData.createFieldGetter(...));
out.setRowKind(RowKind.DELETE);
Defensive patterns

Strategy: try-catch

Validate before calling

// java
if (row instanceof RowDataProjection) {
  throw new IllegalStateException("setRowKind is unsupported on RowDataProjection; mutate the source row instead");
}

Type guard

// java
RowData mutableRow = (row instanceof RowDataProjection)
    ? null  // projection is immutable; use the original row
    : row;

Try / catch

// java
try {
  row.setRowKind(RowKind.INSERT);
} catch (UnsupportedOperationException e) {
  // fall back: copy fields into GenericRowData and set kind on the copy
}

Prevention

When it happens

Trigger: Calling setRowKind(...) on a RowDataProjection instance — e.g. generic Flink code that assumes every RowData is mutable (as with GenericRowData) and tries to change the changelog kind on a projected row.

Common situations: Flink pipeline code applying row-kind updates (dedup, CDC processing) to rows after they passed through a projection; frameworks that mutate RowData in place hitting the wrapper instead of the original row.

Understand the failure class

Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.

Related errors


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

Appendix: source

Thrown at flink/v2.3/flink/src/main/java/org/apache/iceberg/flink/data/RowDataProjection.java:198

  private Object getValue(int pos) {
    Preconditions.checkState(rowData != null, "Row data not wrapped");
    return getters[pos].getFieldOrNull(rowData);
  }

  @Override
  public int getArity() {
    return getters.length;
  }

  @Override
  public RowKind getRowKind() {
    Preconditions.checkState(rowData != null, "Row data not wrapped");
    return rowData.getRowKind();
  }

  @Override
  public void setRowKind(RowKind kind) {
    throw new UnsupportedOperationException("Cannot set row kind in the RowDataProjection");
  }

  @Override
  public boolean isNullAt(int pos) {
    return getValue(pos) == null;
  }

  @Override
  public boolean getBoolean(int pos) {
    return (boolean) getValue(pos);
  }

  @Override
  public byte getByte(int pos) {
    return (byte) getValue(pos);
  }

  @Override

View on GitHub (pinned to 86d9c8fc54)