apache/seatunnel · error · EasysearchConnectorException

UNSUPPORTED_OPERATION

UNSUPPORTED_OPERATION

Error message

Unsupported write row kind: 

What it means

EasysearchRowSerializer.serializeRow switches on the row's RowKind; only INSERT, UPDATE_AFTER, UPDATE_BEFORE and DELETE are serializable to bulk actions. Any other kind hits the default branch and throws UNSUPPORTED_OPERATION.

Source

Thrown at seatunnel-connectors-v2/connector-easysearch/src/main/java/org/apache/seatunnel/connectors/seatunnel/easysearch/serialize/EasysearchRowSerializer.java:67

        this.indexSerializer =
                IndexSerializerFactory.getIndexSerializer(indexInfo.getIndex(), seaTunnelRowType);
        this.seaTunnelRowType = seaTunnelRowType;
        this.keyExtractor =
                KeyExtractor.createKeyExtractor(
                        seaTunnelRowType, indexInfo.getPrimaryKeys(), indexInfo.getKeyDelimiter());
    }

    @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 EasysearchConnectorException(
                        UNSUPPORTED_OPERATION, "Unsupported write row kind: " + row.getRowKind());
        }
    }

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

        try {
            if (key != null) {
                Map<String, String> upsertMetadata = createMetadata(row, key);
                /**
                 * format example: { "update" : {"_index" : "${your_index}", "_id" :
                 * "${your_document_id}"} }\n { "doc" : ${your_document_json}, "doc_as_upsert" :
                 * true }
                 */
                return new StringBuilder()
                        .append("{ \"update\" :")

View on GitHub (pinned to cf67b549a7)

Solutions

  1. Check sink options controlling supported delete/update modes and align them with the data stream.
  2. Filter or transform upstream so only INSERT/UPDATE_AFTER rows reach the sink if deletes are unsupported.
  3. Review the upstream transform/connector emitting the unexpected RowKind.
  4. Verify connector version consistency between transforms and sink.

Example fix

// before
rowStream.map(r -> r); // rows with unsupported kind reach sink
// after
rowStream.filter(r -> r.getRowKind() != RowKind.UPDATE_BEFORE);
Defensive patterns

Strategy: validation

Validate before calling

if (row.getRowKind() != RowKind.INSERT && row.getRowKind() != RowKind.UPDATE_AFTER && row.getRowKind() != RowKind.DELETE) { throw new IllegalArgumentException("row kind not supported by easysearch sink: " + row.getRowKind()); }

Type guard

boolean isSupportedKind(SeaTunnelRow r) { RowKind k = r.getRowKind(); return k == RowKind.INSERT || k == RowKind.UPDATE_AFTER || k == RowKind.DELETE; }

Try / catch

try { sink.write(row); } catch (EasysearchConnectorException e) { /* filter/convert row kind, or dead-letter the row */ }

Prevention

When it happens

Trigger: Feeding a SeaTunnelRow with an unexpected RowKind (e.g. UPDATE_BEFORE forwarded when the serializer expected to skip it internally, or a custom RowKind) into the Easysearch sink with CDC/upsert mode.

Common situations: Upstream transform emitting row kinds not expected by the sink; misconfigured CDC pipeline where DELETE/UPDATE rows are disabled in sink options but still arrive; connector version mismatch changing RowKind handling.

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/902017203bd9c345. Report an issue: GitHub.