apache/seatunnel · error · SeaTunnelRuntimeException

COMMON-02

COMMON-02

Error message

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

What it means

NativeKafkaConnectDeserializationSchema.convertJsonNode converts a Kafka Connect record into a SeaTunnelRow via JsonUtils.toJsonNode(record) and a runtime converter derived from the target schema. Any Throwable during that conversion (payload not matching the Connect schema, unsupported types, nullability violations) is rethrown as CommonError.jsonOperationError containing record.toString(). It signals the record's structure cannot be mapped to the declared SeaTunnel row type.

Source

Thrown at seatunnel-formats/seatunnel-format-compatible-connect-json/src/main/java/org/apache/seatunnel/format/compatible/kafka/connect/json/NativeKafkaConnectDeserializationSchema.java:134

        row.setRowKind(rowKind);
        attachEventTime(row, msg.timestamp());
        if (tablePath.isPresent()) {
            row.setTableId(tablePath.toString());
        }
        out.collect(row);
    }

    private SeaTunnelRow convertJsonNode(Map<String, Object> record) {
        if (MapUtils.isEmpty(record)) {
            return null;
        }

        try {
            org.apache.seatunnel.shade.com.fasterxml.jackson.databind.JsonNode jsonData =
                    JsonUtils.toJsonNode(record);
            return (SeaTunnelRow) runtimeConverter.convert(jsonData, null);
        } catch (Throwable t) {
            throw CommonError.jsonOperationError(FORMAT, record.toString(), t);
        }
    }

    private Map convertToSinkRecord(ConsumerRecord<byte[], byte[]> msg) {
        Map<String, String> headersMap = new HashMap<>();

        for (Header header : msg.headers()) {
            String key = header.key();
            String value = new String(header.value());
            headersMap.put(key, value);
        }

        Map<String, Object> map = new HashMap<>();
        map.put("partition", msg.partition());
        map.put("offset", msg.offset());
        map.put("key", msg.key());
        map.put("value", msg.value());
        map.put("timestamp", msg.timestamp());

View on GitHub (pinned to cf67b549a7)

Solutions

  1. Inspect record.toString() in the error payload and the chained cause to identify the field whose conversion failed.
  2. Update the SeaTunnel source schema to match the current Connect schema (names, types, nullability, logical types like DECIMAL/TIMESTAMP).
  3. If records are not real Kafka Connect records, switch the source format to the plain Kafka JSON deserializer.
  4. Pin producer schema compatibility (backward) so consumers using a fixed SeaTunnel schema are not broken by evolution.

Example fix

// before: schema says amount DECIMAL(10,2) but record sends string
{"amount":"12.30"} -> jsonOperationError
// after: align schema/type on producer side
{"amount":12.30} // or declare amount STRING in SeaTunnel schema and cast in transform
Defensive patterns

Strategy: validation

Validate before calling

// verify record value is a JSON object before conversion
JsonNode value = JsonUtils.toJsonNode(record.value());
if (value == null || !value.isObject()) {
  throw new IllegalArgumentException("Connect record value is not a JSON object: " + record);
}

Type guard

static boolean hasRequiredFields(JsonNode value, String... fields) {
  return value != null && value.isObject()
      && java.util.Arrays.stream(fields).allMatch(f -> value.hasNonNull(f));
}

Try / catch

try {
  SeaTunnelRow row = deserializer.deserialize(record);
} catch (org.apache.seatunnel.api.common.SeaTunnelRuntimeException e) {
  LOG.warn("Failed to convert Connect record: {}", e.getFormattedMessage(), e);
  // route to DLQ or increment error counter instead of failing the task
}

Prevention

When it happens

Trigger: Consuming Kafka Connect records whose schema/value combination the native converter cannot handle: value fields missing from the schema, logical types (decimal/date/timestamp) not matching declared SeaTunnel types, or headers/keys in an unexpected shape during convertJsonNode called from row().

Common situations: Schema registry or producer schema evolved (fields added/removed/renamed) while the SeaTunnel job schema stayed stale; decimal precision/scale or timestamp logical types differing from the declared catalog types; users applying the native connect format to topics that were not written by Kafka Connect.

Related errors


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