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

  1. Inspect the payload in the error and verify it is a valid Debezium change-event envelope with before/after/op
  2. Filter out tombstones and non-DML records (topic cleanup policy / SMT settings on the Debezium side)
  3. Update the connector's database schema to match upstream DDL changes, then restart
  4. 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

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


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