apache/seatunnel · error · SeaTunnelJsonFormatException

UNSUPPORTED_OPERATION

UNSUPPORTED_OPERATION

Error message

Unsupported operation %s for row kind.

What it means

MaxWellJsonSerializationSchema.rowKind2String maps a SeaTunnelRow's RowKind to a Maxwell operation string (insert/delete). RowKinds outside INSERT / UPDATE_BEFORE / DELETE (e.g. UPDATE_AFTER) fall to the default branch and throw UNSUPPORTED_OPERATION, because Maxwell JSON has no representation for that operation.

Source

Thrown at seatunnel-formats/seatunnel-format-json/src/main/java/org/apache/seatunnel/format/json/maxwell/MaxWellJsonSerializationSchema.java:111

            return jsonSerializer.serialize(reuse);
        } catch (Throwable t) {
            throw CommonError.jsonOperationError(FORMAT, row.toString(), t);
        }
    }

    private String rowKind2String(RowKind rowKind) {
        switch (rowKind) {
            case INSERT:
            case UPDATE_AFTER:
                if (mergeUpdateEventFlag && rowKind.equals(RowKind.UPDATE_AFTER)) {
                    return OP_UPDATE;
                }
                return OP_INSERT;
            case UPDATE_BEFORE:
            case DELETE:
                return OP_DELETE;
            default:
                throw new SeaTunnelJsonFormatException(
                        CommonErrorCodeDeprecated.UNSUPPORTED_OPERATION,
                        String.format("Unsupported operation %s for row kind.", rowKind));
        }
    }

    private static SeaTunnelRowType createJsonRowType(SeaTunnelRowType databaseSchema) {
        return new SeaTunnelRowType(
                new String[] {"old", "data", "type", "database", "table", "ts"},
                new SeaTunnelDataType[] {
                    databaseSchema, databaseSchema, STRING_TYPE, STRING_TYPE, STRING_TYPE, LONG_TYPE
                });
    }
}

View on GitHub (pinned to cf67b549a7)

Solutions

  1. Insert a transform or use a sink format that supports update events (e.g. canal-json/debezium-json output)
  2. Coalesce update pairs before the sink so rows are INSERT or DELETE kinds only
  3. Check the upstream source configuration to avoid emitting unsupported RowKinds into this sink
  4. If Maxwell-JSON must be used, pre-convert updates to delete+insert manually

Example fix

// before: CDC source (update pairs) -> MaxwellJson sink => throw
// after: use a format that models updates
sink {
  Kafka {
    format = canal-json
  }
}
Defensive patterns

Strategy: type-guard

Validate before calling

if (row.getRowKind() != RowKind.INSERT && row.getRowKind() != RowKind.UPDATE_BEFORE && row.getRowKind() != RowKind.DELETE) {
    throw new IllegalArgumentException("RowKind " + row.getRowKind() + " not serializable as maxwell-json");
}

Type guard

boolean isMaxwellSerializable(RowKind kind) {
    return kind == RowKind.INSERT || kind == RowKind.UPDATE_BEFORE || kind == RowKind.DELETE;
}

Try / catch

try {
    serializer.serialize(row, out);
} catch (SeaTunnelJsonFormatException e) {
    log.error("Row kind not representable in maxwell json: {}", e.getMessage());
    throw e;
}

Prevention

When it happens

Trigger: serialize() is called with a SeaTunnelRow whose RowKind is e.g. UPDATE_AFTER — typical when a transform or upstream source emits row kinds the Maxwell serializer never anticipated into a sink configured with format=maxwell-json.

Common situations: Chaining a CDC source (which emits UPDATE_BEFORE/UPDATE_AFTER pairs) directly to a Maxwell-JSON sink; transforms that change row kind; custom connectors producing unusual row kinds.

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