apache/iceberg · error · java.lang.UnsupportedOperationException

Could not set a field in the RowDataWrapper because rowData

Error message

Could not set a field in the RowDataWrapper because rowData is read-only

What it means

RowDataWrapper wraps a Flink RowData as an Iceberg StructLike, which is a read-only view: it only supports reading fields via positional getters backed by the underlying RowData. The set(int, T) method is therefore unsupported by design and always throws this UnsupportedOperationException whenever any code attempts to mutate a position through the wrapper. It fires when a component treats the StructLike as writable (e.g., an accumulator or reusable struct in an aggregation path tries to write into it); the offending input is the mutation attempt on the wrapped read-only rowData.

Source

Thrown at flink/v2.3/flink/src/main/java/org/apache/iceberg/flink/RowDataWrapper.java:83

  }

  @Override
  public int size() {
    return types.length;
  }

  @Override
  public <T> T get(int pos, Class<T> javaClass) {
    if (rowData.isNullAt(pos)) {
      return null;
    }

    return javaClass.cast(getters[pos].get(rowData, pos));
  }

  @Override
  public <T> void set(int pos, T value) {
    throw new UnsupportedOperationException(
        "Could not set a field in the RowDataWrapper because rowData is read-only");
  }

  private interface PositionalGetter<T> {
    T get(RowData data, int pos);
  }

  private static PositionalGetter<?> buildGetter(LogicalType logicalType, Type type) {
    switch (logicalType.getTypeRoot()) {
      case TINYINT:
        return (row, pos) -> (int) row.getByte(pos);
      case SMALLINT:
        return (row, pos) -> (int) row.getShort(pos);
      case CHAR:
      case VARCHAR:
        return (row, pos) -> row.getString(pos).toString();

      case BINARY:

View on GitHub (pinned to 86d9c8fc54)

Solutions

  1. Do not call set() on RowDataWrapper; build a mutable StructLike (e.g. a new row / GenericRowData) instead.
  2. Wrap the target in a dedicated writable StructLike implementation for the write path.

Example fix

// before
wrapper.set(0, 42L); // throws
// after
GenericRowData row = new GenericRowData(arity);
row.setField(0, 42L);
Defensive patterns

Strategy: type-guard

Validate before calling

// only use wrapper for read paths
Objects.requireNonNull(wrapper, "wrapper");

Type guard

if (structLike instanceof RowDataWrapper) { throw new IllegalStateException("RowDataWrapper is read-only; use a mutable StructLike for writes"); }

Try / catch

try { wrapper.set(pos, v); } catch (UnsupportedOperationException e) { /* fall back to mutable row */ }

Prevention

When it happens

Trigger: Any code path that treats the wrapper as a writable StructLike and calls set(pos, value) — e.g. generic metadata-writing or update code handed this wrapper as a StructLike row.

Common situations: Reusing a StructLike wrapper designed for reading scan output in a write path; framework code that assumes StructLike implementations are mutable.

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/bb55f55c0601217d. Report an issue: GitHub.