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 adapts a Flink RowData to Iceberg's StructLike interface for reads. Since the underlying RowData is read-only, the set() method has no valid implementation and unconditionally throws UnsupportedOperationException. This signals an attempt to use a read-only projection as a writable struct.
Source
Thrown at flink/v1.20/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
- Do not call set(); construct a new RowData with the desired values instead of mutating the wrapper
- Use a mutable StructLike implementation (e.g. a GenericRowData-backed wrapper or the write-path converter) for writing paths
- Refactor code to build output values via Flink RowData/converters rather than mutating the read wrapper
Example fix
// before wrapper.set(2, newValue); // throws // after GenericRowData out = new GenericRowData(row.getArity()); for (int i = 0; i < row.getArity(); i++) out.setField(i, row.getField(i)); out.setField(2, newValue);
Defensive patterns
Strategy: type-guard
Validate before calling
if (structLike instanceof RowDataWrapper) { throw new IllegalArgumentException("RowDataWrapper is read-only; use a writable StructLike"); } Type guard
boolean isWritable(StructLike s) { return !(s instanceof RowDataWrapper); } Try / catch
try { wrapper.set(pos, v); } catch (UnsupportedOperationException e) { /* fall back to building a new GenericRowData */ } Prevention
- Treat RowDataWrapper as read-only by convention
- Never pass read wrappers into write paths
- Build new RowData objects for mutations
When it happens
Trigger: Calling RowDataWrapper.set(pos, value) on any position; passing a RowDataWrapper where a writable StructLike is expected (e.g. write paths that mutate struct fields in place).
Common situations: Reuse of read-side wrappers in a write path; generic code that treats StructLike as mutable; custom readers/writers built on top of RowDataWrapper that try to fill values in place.
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
- Cannot set row kind in the RowDataProjection
- Not supported yet.
- Not supported yet.
- Altering schema is not supported in the old alterTable API.
- Altering partition keys is not supported yet.
AI-assisted analysis of apache/iceberg@86d9c8fc54 (2026-09-12).
Data as JSON: /api/errors/4a5c282d7912b45d.
Report an issue: GitHub.