{"record":{"id":"afc02404338a1e00","repo":"apache/iceberg","slug":"cannot-set-row-kind-in-the-rowdataprojection","errorCode":null,"errorMessage":"Cannot set row kind in the RowDataProjection","messagePattern":"Cannot set row kind in the RowDataProjection","errorType":"exception","errorClass":"UnsupportedOperationException","httpStatus":null,"severity":"error","filePath":"flink/v1.20/flink/src/main/java/org/apache/iceberg/flink/data/RowDataProjection.java","lineNumber":197,"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":179,"sourceCodeEnd":215,"githubUrl":"https://github.com/apache/iceberg/blob/86d9c8fc543e7c56c9f624eb725f76c9baff9570/flink/v1.20/flink/src/main/java/org/apache/iceberg/flink/data/RowDataProjection.java#L179-L215","documentation":"RowDataProjection wraps an inner RowData to project a subset of fields. Row kind is not part of the projected value, so setRowKind is intentionally unsupported and always throws UnsupportedOperationException. This is a deliberate API contract, not a failure condition.","triggerScenarios":"Calling setRowKind(...) on a RowDataProjection instance, typically when passing the projected RowData to Flink APIs (e.g. sink runtime code or a DataStream map) that mutates row kinds in place.","commonSituations":"Flink changelog pipelines (CDC) where operators like DataStreamScan or custom sinks call setRowKind on projected rows; wrapping projected rows into operators that assume mutable RowData.","solutions":["Set the row kind on the underlying RowData before wrapping it in RowDataProjection.","Copy the projected fields into a new MutableRowData/GenericRowData and set the kind on the copy.","Restructure the pipeline so kind mutation happens before projection.","If kind must flow through projection, use the original RowData rather than the projection at that operator."],"exampleFix":"// before\nRowDataProjection proj = RowDataProjection.of(...);\nproj.setRowKind(RowKind.DELETE); // throws\n// after\nwrapped.setRowKind(RowKind.DELETE);\nRowDataProjection proj = RowDataProjection.of(rowType, positions, types);","handlingStrategy":"fallback","validationCode":null,"typeGuard":null,"tryCatchPattern":"try {\n  row.setRowKind(kind);\n} catch (UnsupportedOperationException e) {\n  // set kind on the wrapped/underlying RowData instead\n  underlyingRow.setRowKind(kind);\n}","preventionTips":["Treat RowDataProjection as immutable; set kinds on the source RowData","Copy projected fields into GenericRowData if downstream needs mutable rows","Reorder pipelines: mutate kind before projecting"],"tags":["flink","rowdata","unsupported-operation"],"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"}