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

  1. Check row.getRowKind() values your source emits; log the first offending kind to confirm.
  2. Ensure the source produces only INSERT/DELETE/UPDATE_BEFORE/UPDATE_AFTER kinds when CDC mode is enabled.
  3. If writing a batch job, do not enable upsert/CDC options on the Iceberg sink so rows are written directly.
  4. 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

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


AI-assisted analysis of apache/seatunnel@cf67b549a7 (2026-09-10). Data as JSON: /api/errors/157ceb779ab4b152. Report an issue: GitHub.