apache/seatunnel · error · SeaTunnelJsonFormatException

UNSUPPORTED_OPERATION

UNSUPPORTED_OPERATION

Error message

Unsupported operation ${rowKind} for row kind.

What it means

CanalJsonSerializationSchema maps a SeaTunnelRow's RowKind to a Canal JSON 'op' value (INSERT/UPDATE/DELETE). Only INSERT, UPDATE_BEFORE/UPDATE_AFTER and DELETE have Canal equivalents; any other RowKind (typically null or an unexpected kind) has no representation, so the serializer throws SeaTunnelJsonFormatException with UNSUPPORTED_OPERATION. Canal's CDC protocol simply cannot express such operations.

Source

Thrown at seatunnel-formats/seatunnel-format-json/src/main/java/org/apache/seatunnel/format/json/canal/CanalJsonSerializationSchema.java:115

            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[] {
                    new ArrayType<>(SeaTunnelRowType[].class, databaseSchema),
                    new ArrayType<>(SeaTunnelRowType[].class, databaseSchema),
                    STRING_TYPE,
                    STRING_TYPE,
                    STRING_TYPE,
                    LONG_TYPE
                });
    }
}

View on GitHub (pinned to cf67b549a7)

Solutions

  1. Ensure every row emitted upstream has setRowKind(INSERT|UPDATE_AFTER|UPDATE_BEFORE|DELETE) before reaching the sink
  2. Fix the source/transform responsible for the unsupported RowKind
  3. Switch the sink format away from canal-json if non-CDC row kinds are legitimately needed
  4. Log row.getRowKind() at the sink boundary while debugging the pipeline

Example fix

// before
SeaTunnelRow row = new SeaTunnelRow(fields); // RowKind never set -> null
// after
SeaTunnelRow row = new SeaTunnelRow(fields);
row.setRowKind(RowKind.INSERT); // or UPDATE_AFTER / UPDATE_BEFORE / DELETE
Defensive patterns

Strategy: validation

Validate before calling

if (row.getRowKind() == null || !EnumSet.of(RowKind.INSERT, RowKind.UPDATE_AFTER, RowKind.UPDATE_BEFORE, RowKind.DELETE).contains(row.getRowKind())) {
    throw new IllegalArgumentException("RowKind not serializable by canal-json: " + row.getRowKind());
}

Type guard

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

Prevention

When it happens

Trigger: Calling serialize(row) on a SeaTunnelRow whose RowKind is null or not one of INSERT, UPDATE_AFTER, UPDATE_BEFORE, DELETE — e.g. a row constructed without setRowKind, or emitted by a custom transform with an exotic kind.

Common situations: Custom sources/transforms that forget to call row.setRowKind(...); pipelines where an upstream change introduces a new RowKind not anticipated by a sink configured with format=canal-json; version upgrades adding new RowKind values.

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