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
- Check the row's RowKind in row.toString(); use a RowKindConverter/filter so only supported kinds (INSERT/UPDATE_AFTER/DELETE) reach the sink
- Ensure the upstream row arity and field types match the Debezium JSON row type built from the database schema
- Convert non-JSON-serializable fields (e.g. byte[], nested maps) to supported types upstream
- 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
- Filter RowKinds unsupported by Debezium sink before serialize
- Keep row arity equal to before/after/op/source/ts_ms schema
- Convert byte[]/custom fields to JSON-friendly types upstream
- Test serialization per RowKind in unit tests
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)