{"record":{"id":"4a5c282d7912b45d","repo":"apache/iceberg","slug":"could-not-set-a-field-in-the-rowdatawrapper-becaus","errorCode":null,"errorMessage":"Could not set a field in the RowDataWrapper because rowData is read-only","messagePattern":"Could not set a field in the RowDataWrapper because rowData is read-only","errorType":"exception","errorClass":"java.lang.UnsupportedOperationException","httpStatus":null,"severity":"error","filePath":"flink/v1.20/flink/src/main/java/org/apache/iceberg/flink/RowDataWrapper.java","lineNumber":83,"sourceCode":"  }\n\n  @Override\n  public int size() {\n    return types.length;\n  }\n\n  @Override\n  public <T> T get(int pos, Class<T> javaClass) {\n    if (rowData.isNullAt(pos)) {\n      return null;\n    }\n\n    return javaClass.cast(getters[pos].get(rowData, pos));\n  }\n\n  @Override\n  public <T> void set(int pos, T value) {\n    throw new UnsupportedOperationException(\n        \"Could not set a field in the RowDataWrapper because rowData is read-only\");\n  }\n\n  private interface PositionalGetter<T> {\n    T get(RowData data, int pos);\n  }\n\n  private static PositionalGetter<?> buildGetter(LogicalType logicalType, Type type) {\n    switch (logicalType.getTypeRoot()) {\n      case TINYINT:\n        return (row, pos) -> (int) row.getByte(pos);\n      case SMALLINT:\n        return (row, pos) -> (int) row.getShort(pos);\n      case CHAR:\n      case VARCHAR:\n        return (row, pos) -> row.getString(pos).toString();\n\n      case BINARY:","sourceCodeStart":65,"sourceCodeEnd":101,"githubUrl":"https://github.com/apache/iceberg/blob/86d9c8fc543e7c56c9f624eb725f76c9baff9570/flink/v1.20/flink/src/main/java/org/apache/iceberg/flink/RowDataWrapper.java#L65-L101","documentation":"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.","triggerScenarios":"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).","commonSituations":"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.","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"],"exampleFix":"// before\nwrapper.set(2, newValue); // throws\n// after\nGenericRowData out = new GenericRowData(row.getArity());\nfor (int i = 0; i < row.getArity(); i++) out.setField(i, row.getField(i));\nout.setField(2, newValue);","handlingStrategy":"type-guard","validationCode":"if (structLike instanceof RowDataWrapper) { throw new IllegalArgumentException(\"RowDataWrapper is read-only; use a writable StructLike\"); }","typeGuard":"boolean isWritable(StructLike s) { return !(s instanceof RowDataWrapper); }","tryCatchPattern":"try { wrapper.set(pos, v); } catch (UnsupportedOperationException e) { /* fall back to building a new GenericRowData */ }","preventionTips":["Treat RowDataWrapper as read-only by convention","Never pass read wrappers into write paths","Build new RowData objects for mutations"],"tags":["flink","unsupported-operation","rowdata"],"backgroundTag":"unsupported-operation","analyzedSha":"86d9c8fc543e7c56c9f624eb725f76c9baff9570","analyzedAt":"2026-09-12T00:46:39.097Z","contentChangedAt":"2026-09-12T00:46:39.097Z","schemaVersion":2},"datasetVersion":"2026-09-14T16:17:12.679Z"}