apache/seatunnel · error · ElasticsearchConnectorException

COMMON_UNSUPPORTED_OPERATION

COMMON_UNSUPPORTED_OPERATION

Error message

Unsupported write row kind: 

What it means

ElasticsearchRowSerializer.serializeRow throws COMMON_UNSUPPORTED_OPERATION when the incoming SeaTunnelRow has a RowKind the serializer cannot handle. Only INSERT/UPDATE_AFTER (upsert), UPDATE_BEFORE and DELETE are supported; anything else (e.g., INSERT arriving on an upsert path is fine, but kinds outside the switch) fails with 'Unsupported write row kind: <kind>'.

Source

Thrown at seatunnel-connectors-v2/connector-elasticsearch/src/main/java/org/apache/seatunnel/connectors/seatunnel/elasticsearch/serialize/ElasticsearchRowSerializer.java:97

        this.seaTunnelRowType = seaTunnelRowType;
        this.keyExtractor =
                KeyExtractor.createKeyExtractor(
                        seaTunnelRowType, indexInfo.getPrimaryKeys(), indexInfo.getKeyDelimiter());
        this.vectorizationFields = vectorizationFields;
        this.vectorDimension = vectorDimension;
    }

    @Override
    public String serializeRow(SeaTunnelRow row) {
        switch (row.getRowKind()) {
            case INSERT:
            case UPDATE_AFTER:
                return serializeUpsert(row);
            case UPDATE_BEFORE:
            case DELETE:
                return serializeDelete(row);
            default:
                throw new ElasticsearchConnectorException(
                        CommonErrorCodeDeprecated.UNSUPPORTED_OPERATION,
                        "Unsupported write row kind: " + row.getRowKind());
        }
    }

    private String serializeUpsert(SeaTunnelRow row) {
        String key = keyExtractor.apply(row);
        Map<String, Object> document = toDocumentMap(row, seaTunnelRowType);
        String documentStr;

        try {
            documentStr = objectMapper.writeValueAsString(document);
        } catch (JsonProcessingException e) {
            throw CommonError.jsonOperationError(
                    "Elasticsearch", "document:" + document.toString(), e);
        }

        if (key != null) {

View on GitHub (pinned to cf67b549a7)

Solutions

  1. Check the RowKind printed in the message and trace which upstream operator emits it
  2. Convert/normalize row kinds upstream (e.g., map INSERT to UPDATE_AFTER for upsert-based writing, or filter UPDATE_BEFORE)
  3. If writing plain batch data, ensure the sink is configured for insert/upsert semantics so INSERT rows take the serializeUpsert path
  4. For CDC sources, keep DELETE/UPDATE_BEFORE kinds intact or drop them depending on desired delete semantics

Example fix

// before
// emitting RowKind.INSERT rows into a CDC upsert pipeline
// after
row.setRowKind(RowKind.UPDATE_AFTER); // normalize before the sink
Defensive patterns

Strategy: validation

Validate before calling

// Filter or normalize row kinds before the sink:
switch (row.getRowKind()) {
    case INSERT:
    case UPDATE_AFTER:
    case UPDATE_BEFORE:
    case DELETE: break; // supported
    default: throw new IllegalStateException("Unsupported RowKind for ES sink: " + row.getRowKind());
}

Type guard

boolean isWritableRowKind(SeaTunnelRow row) {
    RowKind k = row == null ? null : row.getRowKind();
    return k == RowKind.INSERT || k == RowKind.UPDATE_AFTER || k == RowKind.UPDATE_BEFORE || k == RowKind.DELETE;
}

Try / catch

try {
    String json = ElasticsearchRowSerializer.serializeRow(row);
} catch (ElasticsearchConnectorException e) {
    if (String.valueOf(e.getMessage()).startsWith("Unsupported write row kind")) {
        log.warn("Skipping row with kind {}", row.getRowKind());
        return;
    }
    throw e;
}

Prevention

When it happens

Trigger: Writing rows whose RowKind falls into the switch's default branch — e.g., a sink receiving RowKind.INSERT on a path expecting only CDC-updated rows, or a custom/transformed stream emitting unusual row kinds to the Elasticsearch sink.

Common situations: CDC pipelines where upstream emits kinds the Elasticsearch sink does not map; mixing batch (INSERT-only) data with CDC expectations; a transform upstream changing row kinds unexpectedly.

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


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