apache/seatunnel · warning
Received operation, skip
Error message
Received {} operation, skip What it means
A Debezium change record carried an operation type the data-record path does not emit (the handled branches cover insert/read/update-after). deserializeDataChangeRecord logs this warning with the operation name and returns without collecting a row, so the record produces no downstream output.
Solutions
- Identify the operation from the warning; TRUNCATE and heartbeat skips are usually benign.
- If DELETE rows are being skipped unexpectedly, enable/fix the delete-handling mode (e.g. support delete events / tombstone handling) in the deserializer configuration.
- Avoid TRUNCATE on monitored tables or implement truncate propagation in a custom deserializer.
- Filter heartbeat/tombstone records out of the source table list so they never reach the data path.
- Compare source vs sink row counts to confirm no real data loss is hidden behind these skips.
Example fix
// before
} else {
log.warn("Received {} operation, skip", operation);
}
// after: explicitly handle truncate, log others at debug
} else if (operation == Operation.TRUNCATE) {
log.info("Received TRUNCATE for {}, not propagated", record.topic());
} else {
log.warn("Received {} operation, skip", operation);
} Defensive patterns
Strategy: fallback
Validate before calling
// pre-filter non-emittable operations so they never reach the data path
String opName = record.valueSchema().name();
if (opName.endsWith("TransactionMetadata") || opName.endsWith("Heartbeat")) {
return;
} Type guard
boolean isEmittable(Operation op) {
return op == Operation.CREATE || op == Operation.READ || op == Operation.UPDATE;
} Try / catch
// this path does not throw; guard on the emitted row instead
if (row == null) {
log.debug("Record skipped due to operation {}", operation);
return;
}
collector.collect(row); Prevention
- Avoid TRUNCATE on CDC-monitored tables, or handle truncates explicitly in a custom deserializer.
- Exclude heartbeat/tombstone records from the source table list.
- Treat this warning as informational unless source/sink row counts diverge.
- Upgrade the connector if your database emits operations the deserializer does not recognize.
When it happens
Trigger: deserializeDataChangeRecord receives an Operation outside the handled insert/read/update branches — typically TRUNCATE, or a DELETE whose handling path is not enabled by the configured delete-handling mode, or a heartbeat/message record routed to the data path.
Common situations: Running TRUNCATE TABLE on a CDC-monitored table; Debezium heartbeat events reaching the deserializer; connectors where delete handling is disabled and DELETE ops fall into the skip branch; replication events the deserializer version does not recognize.
Understand the failure class
Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.
Related errors
- COMMON-02
- COMMON-02
- Creation of replication slot failed
- Data change record shouldn't use READ operation, the the…
- Failed to authenticate to the MySQL database at
AI-assisted analysis of apache/seatunnel@cf67b549a7 (2026-09-10).
Data as JSON: /api/errors/38a426c17d3336e7.
Report an issue: GitHub.
Appendix: source
Thrown at seatunnel-connectors-v2/connector-cdc/connector-cdc-base/src/main/java/org/apache/seatunnel/connectors/cdc/debezium/row/SeaTunnelRowDebeziumDeserializeSchema.java:312
MetadataUtil.setBinlogFile(before, binlogFile);
MetadataUtil.setBinlogPos(before, binlogPos);
MetadataUtil.setBinlogRow(before, binlogRow);
MetadataUtil.setGtid(before, gtid);
collector.collect(before);
SeaTunnelRow after = extractAfterRow(converters, record, messageStruct, valueSchema);
after.setRowKind(RowKind.UPDATE_AFTER);
after.setTableId(tableId);
MetadataUtil.setDelay(after, delay);
MetadataUtil.setEventTime(after, fetchTimestamp);
MetadataUtil.setSourceTimestamp(after, messageTimestamp);
MetadataUtil.setBinlogFile(after, binlogFile);
MetadataUtil.setBinlogPos(after, binlogPos);
MetadataUtil.setBinlogRow(after, binlogRow);
MetadataUtil.setGtid(after, gtid);
collector.collect(after);
} else {
log.warn("Received {} operation, skip", operation);
}
}
private SeaTunnelRow extractAfterRow(
SeaTunnelRowDebeziumDeserializationConverters runtimeConverter,
SourceRecord record,
Struct value,
Schema valueSchema)
throws Exception {
Schema afterSchema = valueSchema.field(Envelope.FieldName.AFTER).schema();
Struct after = value.getStruct(Envelope.FieldName.AFTER);
return runtimeConverter.convert(record, after, afterSchema);
}
private SeaTunnelRow extractBeforeRow(
SeaTunnelRowDebeziumDeserializationConverters runtimeConverter,
SourceRecord record,View on GitHub (pinned to cf67b549a7)