{"record":{"id":"b5c95f48f868517f","repo":"apache/iceberg","slug":"cannot-set-row-kind-in-the-rowdataprojection-b5c95f","errorCode":null,"errorMessage":"Cannot set row kind in the RowDataProjection","messagePattern":"Cannot set row kind in the RowDataProjection","errorType":"exception","errorClass":"java.lang.UnsupportedOperationException","httpStatus":null,"severity":"error","filePath":"flink/v2.1/flink/src/main/java/org/apache/iceberg/flink/data/RowDataProjection.java","lineNumber":198,"sourceCode":"  private Object getValue(int pos) {\n    Preconditions.checkState(rowData != null, \"Row data not wrapped\");\n    return getters[pos].getFieldOrNull(rowData);\n  }\n\n  @Override\n  public int getArity() {\n    return getters.length;\n  }\n\n  @Override\n  public RowKind getRowKind() {\n    Preconditions.checkState(rowData != null, \"Row data not wrapped\");\n    return rowData.getRowKind();\n  }\n\n  @Override\n  public void setRowKind(RowKind kind) {\n    throw new UnsupportedOperationException(\"Cannot set row kind in the RowDataProjection\");\n  }\n\n  @Override\n  public boolean isNullAt(int pos) {\n    return getValue(pos) == null;\n  }\n\n  @Override\n  public boolean getBoolean(int pos) {\n    return (boolean) getValue(pos);\n  }\n\n  @Override\n  public byte getByte(int pos) {\n    return (byte) getValue(pos);\n  }\n\n  @Override","sourceCodeStart":180,"sourceCodeEnd":216,"githubUrl":"https://github.com/apache/iceberg/blob/86d9c8fc543e7c56c9f624eb725f76c9baff9570/flink/v2.1/flink/src/main/java/org/apache/iceberg/flink/data/RowDataProjection.java#L180-L216","documentation":"RowDataProjection wraps an inner RowData and projects it to a subset of fields. Setting the row kind on a projection is not a meaningful operation, so setRowKind unconditionally throws UnsupportedOperationException. This is an intentionally unsupported mutating method on a read-only projection view.","triggerScenarios":"Calling setRowKind(...) on a RowDataProjection instance obtained from Iceberg's Flink source/scan pipeline (e.g. attempting to mark a projected row as INSERT/DELETE before emitting to a sink).","commonSituations":"Custom Flink operators or sinks that assume any RowData is mutable and call setRowKind; UDFs that re-tag rows downstream of the Iceberg reader.","solutions":["Wrap the projected row in a copy (e.g. GenericRowData) and set the kind on that copy","Use a BinaryRowData/JoinedRowData wrapper that supports row kind","Apply the row-kind change upstream, before or after projection, on your own RowData"],"exampleFix":"// before\nprojected.setRowKind(RowKind.DELETE); // throws\n// after\nGenericRowData copy = new GenericRowData(projected.getArity());\nfor (int i = 0; i < projected.getArity(); i++) copy.setField(i, RowData.createFieldGetter(...).getFieldOrNull(projected));\ncopy.setRowKind(RowKind.DELETE);","handlingStrategy":"fallback","validationCode":null,"typeGuard":"RowData mutable = (projected instanceof RowDataProjection) ? copyOf(projected) : projected;","tryCatchPattern":"try { row.setRowKind(kind); } catch (UnsupportedOperationException e) { GenericRowData copy = copyToGenericRowData(row); copy.setRowKind(kind); emit(copy); }","preventionTips":["Treat RowDataProjection as read-only","Copy to GenericRowData before mutating row kind","Don't pass projections directly to sinks that mutate row kind"],"tags":["flink","rowdata","projection","immutable"],"backgroundTag":"unsupported-operation","analyzedSha":"86d9c8fc543e7c56c9f624eb725f76c9baff9570","analyzedAt":"2026-09-12T00:46:39.097Z","contentChangedAt":"2026-09-12T00:46:39.097Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}