apache/seatunnel · error · IllegalArgumentException
Unrecognized row kind:<rowKind>
Error message
Unrecognized row kind:<rowKind>
What it means
SeaTunnelRowSerializer.parseDeleteSign maps RowKind to the Doris stream-load delete sign (0 for insert/update-after, 1 for delete/update-before). RowKind.READ or any unexpected kind throws IllegalArgumentException because the serializer cannot decide whether the row is an insert or a delete.
Source
Thrown at seatunnel-connectors-v2/connector-doris/src/main/java/org/apache/seatunnel/connectors/doris/serialize/SeaTunnelRowSerializer.java:123
}
public byte[] buildJsonString(SeaTunnelRow row) {
return serialize.serialize(row);
}
public byte[] buildCSVString(SeaTunnelRow row) {
return serialize.serialize(row);
}
public String parseDeleteSign(RowKind rowKind) {
if (RowKind.INSERT.equals(rowKind) || RowKind.UPDATE_AFTER.equals(rowKind)) {
return "0";
} else if (RowKind.DELETE.equals(rowKind) || RowKind.UPDATE_BEFORE.equals(rowKind)) {
return "1";
} else {
throw new IllegalArgumentException("Unrecognized row kind:" + rowKind.toString());
}
}
@Override
public void open() throws IOException {}
@Override
public byte[] serialize(SeaTunnelRow seaTunnelRow) throws IOException {
if (enableDelete) {
List<Object> newFields = new ArrayList<>(Arrays.asList(seaTunnelRow.getFields()));
newFields.add(parseDeleteSign(seaTunnelRow.getRowKind()));
seaTunnelRow = new SeaTunnelRow(newFields.toArray());
}
if (JSON.equals(type)) {
return buildJsonString(seaTunnelRow);View on GitHub (pinned to cf67b549a7)
Solutions
- Ensure the source emits CDC semantics (CDC-enabled source or SeaTunnelRow with correct RowKind), or disable delete-sign handling for non-CDC pipelines
- Normalize RowKind in a transform: map READ rows to INSERT before the sink
- Check that upstream transforms don't overwrite the RowKind
Example fix
// before SeaTunnelRow row = new SeaTunnelRow(values); // RowKind.READ // after row.setRowKind(RowKind.INSERT);
Defensive patterns
Strategy: type-guard
Validate before calling
RowKind k = row.getRowKind();
if (!(k == RowKind.INSERT || k == RowKind.UPDATE_AFTER || k == RowKind.DELETE || k == RowKind.UPDATE_BEFORE)) throw new IllegalStateException("non-CDC row in CDC sink: " + k); Type guard
boolean isCdcRowKind(RowKind k) { return k == RowKind.INSERT || k == RowKind.UPDATE_AFTER || k == RowKind.DELETE || k == RowKind.UPDATE_BEFORE; } Prevention
- Only enable delete-sign/CDC mode with CDC-capable sources
- Insert a transform to normalize RowKind.READ to INSERT for batch data
- Assert RowKind in tests covering your pipeline
When it happens
Trigger: Sink receiving rows whose RowKind is not INSERT/UPDATE_AFTER/DELETE/UPDATE_BEFORE — typically RowKind.READ produced by a non-CDC source when `cdc-enabled`/deletable semantics were wrongly assumed, or custom transforms resetting the row kind.
Common situations: Feeding a batch/snapshot source into a Doris sink configured for CDC (enable-delete with primary-key table); a transform that constructs SeaTunnelRow with RowKind.READ; version changes in RowKind enum handling.
Understand the failure class
Background: Invalid enum value errors: "Unknown type", "Invalid scope", "must be one of" — when a string is not on the library's allowed list — this error's family across 23 libraries.
Related errors
- COMMON_UNSUPPORTED_OPERATION
- UNSUPPORTED_OPERATION
- UNSUPPORTED_OPERATION
- Unsupported schemaChangeEvent : <eventType>
- UNSUPPORTED_OPERATION
AI-assisted analysis of apache/seatunnel@cf67b549a7 (2026-09-10).
Data as JSON: /api/errors/4d46c147e18f839f.
Report an issue: GitHub.