apache/seatunnel · error · UnsupportedOperationException
Unknown row kind:
Error message
Unknown row kind:
What it means
BaseDeltaTaskWriter.write throws UnsupportedOperationException when a CDC row's RowKind is not one of the supported kinds (INSERT, UPDATE_AFTER -> upsert, UPDATE_BEFORE/DELETE -> delete). Any other RowKind reaches the default branch and is rejected. This guards the equality-delete upsert writer against unexpected CDC semantics.
Source
Thrown at seatunnel-connectors-v2/connector-iceberg/src/main/java/org/apache/seatunnel/connectors/seatunnel/iceberg/sink/writer/BaseDeltaTaskWriter.java:107
}
writer.write(row);
break;
case UPDATE_BEFORE:
if (upsert) {
break;
}
writer.delete(row);
break;
case DELETE:
if (upsert) {
writer.deleteKey(keyProjection.wrap(row));
} else {
writer.delete(row);
}
break;
default:
throw new UnsupportedOperationException("Unknown row kind: " + row.getRowKind());
}
}
class RowDataDeltaWriter extends BaseEqualityDeltaWriter {
RowDataDeltaWriter(PartitionKey partition) {
super(partition, schema, deleteSchema);
}
@Override
protected StructLike asStructLike(Record data) {
return wrapper.wrap(data);
}
@Override
protected StructLike asStructLikeKey(Record data) {
return keyWrapper.wrap(data);
}
}View on GitHub (pinned to cf67b549a7)
Solutions
- Check row.getRowKind() values your source emits; log the first offending kind to confirm.
- Ensure the source produces only INSERT/DELETE/UPDATE_BEFORE/UPDATE_AFTER kinds when CDC mode is enabled.
- If writing a batch job, do not enable upsert/CDC options on the Iceberg sink so rows are written directly.
- Upgrade SeaTunnel if the source recently introduced a new RowKind not yet handled by the sink.
Example fix
// before row.setRowKind(customKind); // unsupported kind reaching writer // after row.setRowKind(RowKind.INSERT); // or UPDATE_AFTER/UPDATE_BEFORE/DELETE for CDC
Defensive patterns
Strategy: validation
Validate before calling
if (cdcMode && row.getRowKind() != RowKind.INSERT && row.getRowKind() != RowKind.UPDATE_AFTER && row.getRowKind() != RowKind.UPDATE_BEFORE && row.getRowKind() != RowKind.DELETE) { throw new IllegalStateException("Unsupported RowKind for Iceberg upsert: " + row.getRowKind()); } Try / catch
try { writer.write(row); } catch (UnsupportedOperationException e) { if (e.getMessage().startsWith("Unknown row kind")) { log.error("Unsupported RowKind from source: {}", e.getMessage()); /* skip/DLQ row */ } else throw e; } Prevention
- Only enable CDC/upsert mode with sources that emit standard INSERT/UPDATE_BEFORE/UPDATE_AFTER/DELETE kinds
- Use INSERT mode for batch (non-CDC) Iceberg writes
- Log RowKind distribution in a sample run before enabling equality-delete writers
When it happens
Trigger: Writing a row to the Iceberg sink in CDC/upsert mode whose SeaTunnel RowKind is outside the supported set (e.g. custom/future kinds or rows not properly marked by the source).
Common situations: Batch (non-CDC) job writing rows with a RowKind the CDC path does not expect; source connector emitting exotic row kinds; enabling 'schema-save-mode'/'upsert' for a source that does not produce proper CDC markers.
Related errors
- Unknown row kind: ${rowKind}
- Multiple incremental splits are not supported
- not supported create new Offset by committed offset.
- The SplitChange type of %s is not supported.
- should not call here, error
AI-assisted analysis of apache/seatunnel@cf67b549a7 (2026-09-10).
Data as JSON: /api/errors/157ceb779ab4b152.
Report an issue: GitHub.