apache/seatunnel · error · KuduConnectorException
UNSUPPORTED_OPERATION
UNSUPPORTED_OPERATION
Error message
Unsupported write row kind:
What it means
KuduRowSerializer.serializeRow() maps a SeaTunnelRow's RowKind to a Kudu write operation (INSERT/UPSERT/DELETE). RowKinds outside the supported set fall into the default branch and throw KuduConnectorException with UNSUPPORTED_OPERATION, naming the offending RowKind.
Source
Thrown at seatunnel-connectors-v2/connector-kudu/src/main/java/org/apache/seatunnel/connectors/seatunnel/kudu/serialize/KuduRowSerializer.java:68
@Override
public Operation serializeRow(SeaTunnelRow row) {
Operation operation;
switch (row.getRowKind()) {
case INSERT:
if (saveMode == KuduSinkConfig.SaveMode.OVERWRITE) {
operation = kuduTable.newUpsert();
break;
}
operation = kuduTable.newInsert();
break;
case UPDATE_AFTER:
operation = kuduTable.newUpsert();
break;
case DELETE:
operation = kuduTable.newDelete();
break;
default:
throw new KuduConnectorException(
CommonErrorCodeDeprecated.UNSUPPORTED_OPERATION,
"Unsupported write row kind: " + row.getRowKind());
}
transform(operation, row);
return operation;
}
private void transform(Operation operation, SeaTunnelRow element) {
PartialRow row = operation.getRow();
for (int columnIndex = 0; columnIndex < seaTunnelRowType.getTotalFields(); columnIndex++) {
SeaTunnelDataType<?> type = seaTunnelRowType.getFieldType(columnIndex);
try {
switch (type.getSqlType()) {
case BOOLEAN:
case TINYINT:
case SMALLINT:
case INT:
case BIGINT:View on GitHub (pinned to cf67b549a7)
Solutions
- Preprocess the stream so only INSERT/UPDATE_AFTER/DELETE rows reach the sink (e.g. use a deduplicate transform)
- Configure the sink to upsert (UPDATE_AFTER maps to UPSERT)
- Filter out unsupported RowKinds before the sink
Example fix
// before // UPDATE_BEFORE rows sent to kudu sink // after // add transform/dropRowKind or route UPDATE_AFTER -> UPSERT before sink
Defensive patterns
Strategy: validation
Validate before calling
// Filter unsupported RowKinds before the sink
if (row.getRowKind() == RowKind.INSERT || row.getRowKind() == RowKind.UPDATE_AFTER || row.getRowKind() == RowKind.DELETE) { /* send to sink */ } else { /* drop or route */ } Try / catch
try { serializer.serializeRow(row); } catch (KuduConnectorException e) {
if ("UNSUPPORTED_OPERATION".equals(e.getSeaTunnelErrorCode())) { /* drop/transform row */ }
} Prevention
- Use a deduplicate/transform to collapse CDC UPDATE_BEFORE+UPDATE_AFTER pairs
- Route UPDATE_AFTER rows as upserts
- Filter RowKind before the Kudu sink
When it happens
Trigger: Writing a row whose RowKind is UPDATE_BEFORE, UPDATE_AFTER, or any kind not mapped to a Kudu operation when using the Kudu sink.
Common situations: CDC pipelines (e.g. MySQL CDC) emitting UPDATE_BEFORE/UPDATE_AFTER rows directly into a Kudu sink without aggregation or without configuring sink support for update semantics.
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
- UNSUPPORTED_ROW_KIND
- UNSUPPORTED_DATA_TYPE
- Unsupported row kind.
- UNSUPPORTED_OPERATION
- MultiTableWriterRunnable can't find writer for tableId:
AI-assisted analysis of apache/seatunnel@cf67b549a7 (2026-09-10).
Data as JSON: /api/errors/ca9f7e0e0f580874.
Report an issue: GitHub.