apache/seatunnel · error · MongodbConnectorException
ILLEGAL_ARGUMENT
ILLEGAL_ARGUMENT
Error message
MongoDB CDC data change record has no value:
What it means
MongodbRecordUtils.getOperationType reads the Debezium-style SourceRecord's value Struct to determine the change operation. If the record's value is null it cannot classify the change and throws ILLEGAL_ARGUMENT — a null value normally means a tombstone, which this connector does not treat as a valid change event.
Source
Thrown at seatunnel-connectors-v2/connector-cdc/connector-cdc-mongodb/src/main/java/org/apache/seatunnel/connectors/seatunnel/cdc/mongodb/utils/MongodbRecordUtils.java:82
/** Check the sourceRecord is snapshot record. */
public static boolean isSnapshotRecord(SourceRecord sourceRecord) {
return "true".equals(getOffsetValue(sourceRecord, COPY_KEY_FIELD));
}
/** Check the sourceRecord is heartbeat event. */
public static boolean isHeartbeatEvent(SourceRecord sourceRecord) {
return "true".equals(getOffsetValue(sourceRecord, HEARTBEAT_KEY_FIELD));
}
public static boolean isDataChangeRecord(SourceRecord sourceRecord) {
return !isWatermarkEvent(sourceRecord) && !isHeartbeatEvent(sourceRecord);
}
public static @Nonnull OperationType getOperationType(@Nonnull SourceRecord sourceRecord) {
Struct value = (Struct) sourceRecord.value();
if (value == null) {
throw new MongodbConnectorException(
ILLEGAL_ARGUMENT,
"MongoDB CDC data change record has no value: " + sourceRecord);
}
String operationType = null;
if (value.schema().field(OPERATION_TYPE) != null) {
operationType = value.getString(OPERATION_TYPE);
}
if (StringUtils.isEmpty(operationType)) {
if (isSnapshotRecord(sourceRecord)) {
return OperationType.INSERT;
}
throw new MongodbConnectorException(
ILLEGAL_ARGUMENT,
"MongoDB CDC data change record has no operationType field: " + sourceRecord);
}
return OperationType.fromString(operationType);
}View on GitHub (pinned to cf67b549a7)
Solutions
- Skip records whose value is null before calling getOperationType (tombstones carry no change data)
- Filter out non-data events with MongodbRecordUtils.isWatermarkEvent/isHeartbeatEvent before processing
- Disable tombstone emission at the source if null-value records are not expected
Example fix
// before
OperationType op = MongodbRecordUtils.getOperationType(sourceRecord);
// after
if (sourceRecord.value() == null) {
return; // tombstone / non-data record
}
OperationType op = MongodbRecordUtils.getOperationType(sourceRecord); Defensive patterns
Strategy: validation
Validate before calling
if (sourceRecord == null || sourceRecord.value() == null) {
return; // tombstone / non-data record, skip
} Type guard
boolean isDataRecord(SourceRecord r) {
return r != null && r.value() instanceof Struct
&& !MongodbRecordUtils.isWatermarkEvent(r) && !MongodbRecordUtils.isHeartbeatEvent(r);
} Try / catch
try {
OperationType op = MongodbRecordUtils.getOperationType(record);
} catch (MongodbConnectorException e) {
log.warn("Skipping record without value: {}", record.topic());
} Prevention
- Filter tombstone (null-value) records before classification
- Exclude watermark/heartbeat events from change processing
- Route only MongoDB CDC data records into getOperationType
When it happens
Trigger: sourceRecord.value() returns null (tombstone record emitted after a delete, or a heartbeat/schema-change record with no payload) and is passed to getOperationType.
Common situations: Kafka-connect-style tombstones enabled so deletes emit a second null-value record; connector version emitting record kinds the utility was not designed for; a misrouted record from a different topic/stream reaching this code.
Understand the failure class
Background: "must not be empty", "cannot be empty" — required-field validation errors across open-source libraries — this error's family across 41 libraries.
Related errors
AI-assisted analysis of apache/seatunnel@cf67b549a7 (2026-09-10).
Data as JSON: /api/errors/def4b8ae4f727966.
Report an issue: GitHub.