apache/flink · error · UnsupportedOperationException
Unsupported operation '%s' for row kind.
Error message
Unsupported operation '%s' for row kind.
What it means
Thrown by DebeziumJsonSerializationSchema.serialize when the incoming RowData has a RowKind not in {INSERT, UPDATE_AFTER, UPDATE_BEFORE, DELETE}. The serializer maps INSERT/UPDATE_AFTER to the 'r'/'c' ops and UPDATE_BEFORE/DELETE to the 'd' op; any other RowKind hits the default branch with UnsupportedOperationException, which is then wrapped into RuntimeException('Could not serialize row ...').
Source
Thrown at flink-formats/flink-json/src/main/java/org/apache/flink/formats/json/debezium/DebeziumJsonSerializationSchema.java:94
@Override
public byte[] serialize(RowData rowData) {
try {
switch (rowData.getRowKind()) {
case INSERT:
case UPDATE_AFTER:
genericRowData.setField(0, null);
genericRowData.setField(1, rowData);
genericRowData.setField(2, OP_INSERT);
return jsonSerializer.serialize(genericRowData);
case UPDATE_BEFORE:
case DELETE:
genericRowData.setField(0, rowData);
genericRowData.setField(1, null);
genericRowData.setField(2, OP_DELETE);
return jsonSerializer.serialize(genericRowData);
default:
throw new UnsupportedOperationException(
format(
"Unsupported operation '%s' for row kind.",
rowData.getRowKind()));
}
} catch (Throwable t) {
throw new RuntimeException(format("Could not serialize row '%s'.", rowData), t);
}
}
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
DebeziumJsonSerializationSchema that = (DebeziumJsonSerializationSchema) o;View on GitHub (pinned to 2f3c205e92)
Solutions
- Ensure upstream operators only emit RowKind.INSERT, UPDATE_BEFORE, UPDATE_AFTER, or DELETE into a debezium-json sink.
- Normalize RowKinds in a preceding map: convert non-CDC kinds (e.g. clamp everything else to INSERT) before the sink.
- If the exception surfaces as 'Could not serialize row', inspect the cause — this UnsupportedOperationException indicates the row kind, not the payload, is the problem.
Example fix
// before genericRow.setRowKind(RowKind.fromShortValue((short) 7)); // unknown kind out.collect(genericRow); // after genericRow.setRowKind(RowKind.INSERT); out.collect(genericRow);
Defensive patterns
Strategy: type-guard
Type guard
private static final Set<RowKind> CDC_KINDS = EnumSet.of(
RowKind.INSERT, RowKind.UPDATE_BEFORE, RowKind.UPDATE_AFTER, RowKind.DELETE);
static boolean isCdcRowKind(RowData row) {
return CDC_KINDS.contains(row.getRowKind());
} Try / catch
Catch RuntimeException around serialization, inspect getCause() instanceof UnsupportedOperationException and its message for 'row kind' before deciding to skip or fail.
Prevention
- Validate RowKind in a map before the debezium-json sink.
- Never construct RowKinds via fromShortValue with unchecked external input.
When it happens
Trigger: Serializing a RowData whose RowKind is a custom/extended kind beyond the four CDC kinds — practically only reachable via a custom pipeline that sets RowKind via valueOf on an unknown short value, or a downstream operator emitting a non-standard kind into a debezium-json sink.
Common situations: Custom sources or ProcessFunctions reusing RowKind short codes outside 0..3; version changes introducing new RowKind enum values; test harnesses constructing GenericRowData with arbitrary RowKind.
Related errors
- Could not serialize row '%s'.
- Unsupported operation '%s' for row kind.
- Unsupported operation '%s' for row kind.
- Debezium JSON serialization doesn't support '%s.%s' option b
- Could not serialize row '%s'.
AI-assisted analysis of apache/flink@2f3c205e92 (2026-08-14).
Data as JSON: /api/errors/63eaeaae9070f149.
Report an issue: GitHub.