apache/iceberg · error · 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 implements Iceberg's StructLike wrapper over Flink RowData, which is read-only. Its set(pos, value) method is therefore unimplemented and always throws UnsupportedOperationException — you cannot mutate wrapped Flink RowData through this wrapper.

Solutions

  1. Wrap a mutable record type instead (e.g. Iceberg's Record or a GenericRecord) when writes are needed.
  2. Copy the RowData into a writable structure before passing it to APIs that call set().
  3. Avoid calling set(); only read via get() from this wrapper.

Example fix

// before
RowDataWrapper w = new RowDataWrapper(...); w.set(0, val); // throws
// after
Record rec = GenericRecord.create(schema);
rec.set(0, val);
Defensive patterns

Strategy: type-guard

Validate before calling

if (needsMutation) { /* use a mutable Record instead of RowDataWrapper */ }

Type guard

boolean isMutable(StructLike s) { return !(s instanceof RowDataWrapper); }

Try / catch

if (isMutable(structLike)) { structLike.set(pos, value); } else { /* copy into Record first */ }

Prevention

When it happens

Trigger: Passing a RowDataWrapper as a StructLike to any Iceberg API that mutates records, e.g. writing into a StructLike via internal record builders, copy operations, or generic updaters that call StructLike.set.

Common situations: Using Flink RowData in an Iceberg code path that expects a writable StructLike (e.g. building partition keys or writing records generically); reuse of a read wrapper in a write context.

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

Appendix: source

Thrown at flink/v2.2/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)