apache/seatunnel · error · SeaTunnelRuntimeException

COMMON-02

COMMON-02

Error message

Json JSON convert/parse '<payload>' operation failed.

What it means

DebeziumJsonSerializationSchema.serialize wraps any Throwable from mapping a SeaTunnelRow to the Debezium JSON envelope (before/after/op/source/ts_ms) into jsonOperationError. The offending row's toString is embedded. It means the row's RowKind, arity, or field types are incompatible with the Debezium envelope the serializer builds.

Solutions

  1. Check the row's RowKind in row.toString(); use a RowKindConverter/filter so only supported kinds (INSERT/UPDATE_AFTER/DELETE) reach the sink
  2. Ensure the upstream row arity and field types match the Debezium JSON row type built from the database schema
  3. Convert non-JSON-serializable fields (e.g. byte[], nested maps) to supported types upstream
  4. Reproduce in testSerializationDeserialization with the failing row and fix the producer accordingly

Example fix

// before: TRUNCATE RowKind reaches Debezium sink -> Unsupported operation
row.setRowKind(RowKind.TRUNCATE);
// after: filter unsupported kinds before sink
if (row.getRowKind() == RowKind.TRUNCATE) return; // or map to DELETE
Defensive patterns

Strategy: validation

Validate before calling

Set<RowKind> supported = Set.of(RowKind.INSERT, RowKind.UPDATE_AFTER, RowKind.DELETE);
if (!supported.contains(row.getRowKind())) {
    throw new IllegalArgumentException("Unsupported RowKind " + row.getRowKind());
}

Type guard

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

Try / catch

try {
    byte[] out = serializer.serialize(row);
} catch (SeaTunnelRuntimeException e) {
    log.error("Debezium serialize failed for row {}", row, e);
    throw e;
}

Prevention

When it happens

Trigger: serialize(SeaTunnelRow) hits the UnsupportedOperationException for unsupported RowKind, or Jackson fails serializing field values, or the row's field count differs from createJsonRowType's expected schema (before, after, op, source, ts_ms).

Common situations: Sink receives DELETE/UPDATE rows while configured schema only supports INSERT; upstream transforms producing wrong arity rows; byte[] or custom-typed fields Jackson cannot serialize; RowKind like TRUNCATE not handled.

Understand the failure class

Background: "JSON serialization failed", "not JSON serializable", "Failed to serialize": why JSON marshaling errors happen and how to fix them — this error's family across 46 libraries.

Related errors


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

Appendix: source

Thrown at seatunnel-formats/seatunnel-format-json/src/main/java/org/apache/seatunnel/format/json/debezium/DebeziumJsonSerializationSchema.java:120

                        return null;
                    }
                case DELETE:
                    genericRow.setField(0, row);
                    genericRow.setField(1, null);
                    genericRow.setField(2, OP_DELETE);
                    genericRow.setField(3, source);
                    if (row.getOptions() != null
                            && row.getOptions().containsKey(EVENT_TIME.getName())) {
                        genericRow.setField(4, row.getOptions().get(EVENT_TIME.getName()));
                    }
                    return jsonSerializer.serialize(genericRow);
                default:
                    throw new UnsupportedOperationException(
                            String.format(
                                    "Unsupported operation '%s' for row kind.", row.getRowKind()));
            }
        } catch (Throwable t) {
            throw CommonError.jsonOperationError(FORMAT, row.toString(), t);
        }
    }

    private static SeaTunnelRowType createJsonRowType(SeaTunnelRowType databaseSchema) {
        return new SeaTunnelRowType(
                new String[] {"before", "after", "op", "source", "ts_ms"},
                new SeaTunnelDataType[] {
                    databaseSchema,
                    databaseSchema,
                    STRING_TYPE,
                    new MapType<>(BasicType.STRING_TYPE, BasicType.STRING_TYPE),
                    LONG_TYPE
                });
    }
}

View on GitHub (pinned to cf67b549a7)