apache/seatunnel · error · SeaTunnelRuntimeException
COMMON-02
COMMON-02
Error message
Json JSON convert/parse '<payload>' operation failed.
What it means
DebeziumJsonDeserializationSchema.deserializeMessage wraps any Exception from parsing the Debezium envelope and converting the payload to a SeaTunnelRow into jsonOperationError, unless ignoreParseErrors is enabled. The raw message is embedded in the message. It indicates the Debezium JSON message (before/after/op/source/ts_ms) was missing fields, had unexpected shapes, or the value converters rejected data.
Source
Thrown at seatunnel-formats/seatunnel-format-json/src/main/java/org/apache/seatunnel/format/json/debezium/DebeziumJsonDeserializationSchema.java:110
@Override
public void deserialize(byte[] message, Collector<SeaTunnelRow> out) {
deserializeMessage(message, out, tablePath);
}
public void deserializeMessage(
byte[] message, Collector<SeaTunnelRow> out, TablePath tablePath) {
if (message == null || message.length == 0) {
// skip tombstone messages
return;
}
try {
JsonNode payload = getPayload(jsonDeserializer.deserializeToJsonNode(message));
parsePayload(out, tablePath, payload);
} catch (Exception e) {
// a big try catch to protect the processing.
if (!ignoreParseErrors) {
throw CommonError.jsonOperationError(FORMAT, new String(message), e);
}
}
}
public void parsePayload(Collector<SeaTunnelRow> out, JsonNode payload) throws IOException {
parsePayload(out, tablePath, payload);
}
private void parsePayload(Collector<SeaTunnelRow> out, TablePath tablePath, JsonNode payload)
throws IOException {
String op = payload.get(OP_KEY).asText();
JsonNode tsNode = payload.get(DATA_TS);
switch (op) {
case OP_CREATE:
case OP_READ:
SeaTunnelRow insert = debeziumRowConverter.parse(payload.get(DATA_AFTER));
insert.setRowKind(RowKind.INSERT);View on GitHub (pinned to cf67b549a7)
Solutions
- Inspect the payload in the error and verify it is a valid Debezium change-event envelope with before/after/op
- Filter out tombstones and non-DML records (topic cleanup policy / SMT settings on the Debezium side)
- Update the connector's database schema to match upstream DDL changes, then restart
- Set debezium-json ignore-parse-errors=true if occasional dirty events should be skipped
Example fix
// before: raw topic parsed as debezium-json format = JsonFormat // after: ensure events are real Debezium envelopes or switch format DebeziumJsonDeserializationSchema.builder(databaseSchema,...).setIgnoreParseErrors(true).build(); // and enable Debezium's ExtractNewRecordState only if schema matches
Defensive patterns
Strategy: try-catch
Validate before calling
JsonNode root = mapper.readTree(message);
boolean isDebeziumEvent = root.isObject() && root.has("op") && (root.has("before") || root.has("after")); Type guard
boolean isDebeziumEnvelope(JsonNode n) {
return n != null && n.isObject() && n.hasNonNull("op")
&& (n.has("before") || n.has("after"));
} Try / catch
try {
schema.deserialize(message, out);
} catch (SeaTunnelRuntimeException e) {
log.warn("Skip malformed debezium event: {}", new String(message), e);
} Prevention
- Enable ignore-parse-errors for production CDC jobs
- Exclude tombstone records (Debezium tombstones.on.delete=false)
- Keep database schema in connector config in sync with upstream DDL
- Confirm topic format matches 'debezium-json' exactly
When it happens
Trigger: deserializeMessage receives bytes whose JSON either fails envelope parsing (getPayload) or whose before/after fields do not match the configured database schema during parsePayload: missing 'op', tombstone events, schema-registry style wrapping, or type-incompatible values.
Common situations: Debezium version change changing envelope layout (e.g. optional 'source' fields); snapshot/tombstone (null-value) records reaching the connector; column type changes after upstream DDL; consumers configured with 'debezium-json' format against raw JSON topics.
Understand the failure class
Background: JSON parse error: "Unexpected token" / "not valid JSON" / "failed to parse" — what JSON parsers are really complaining about — this error's family across 45 libraries.
Related errors
- Unknown table change type:
- Unsupported type: %s
- UNSUPPORTED_DATA_TYPE
- Unknown operation type '%s'.
- COMMON-02
AI-assisted analysis of apache/seatunnel@cf67b549a7 (2026-09-10).
Data as JSON: /api/errors/b755f336a59fb56e.
Report an issue: GitHub.