apache/seatunnel · error · java.lang.IllegalStateException
Data change record shouldn't use READ operation, the the rec
Error message
Data change record shouldn't use READ operation, the the record is %s.
What it means
During buffering of change records (rewriteOutputBuffer), JdbcSourceFetchTaskContext expects only INSERT/UPDATE/DELETE operations; a READ (snapshot-style) event appearing in the change buffer violates the incremental-phase contract, so it throws IllegalStateException. READ events are only valid during snapshot reading, not in the incremental output buffer where upsert semantics are applied.
Source
Thrown at seatunnel-connectors-v2/connector-cdc/connector-cdc-base/src/main/java/org/apache/seatunnel/connectors/cdc/base/source/reader/external/JdbcSourceFetchTaskContext.java:136
Instant fetchTs =
Instant.ofEpochMilli((Long) source.get(Envelope.FieldName.TIMESTAMP));
SourceRecord record =
new SourceRecord(
changeRecord.sourcePartition(),
changeRecord.sourceOffset(),
changeRecord.topic(),
changeRecord.kafkaPartition(),
changeRecord.keySchema(),
changeRecord.key(),
changeRecord.valueSchema(),
envelope.read(after, source, fetchTs));
outputBuffer.put(key, record);
break;
case DELETE:
outputBuffer.remove(key);
break;
case READ:
throw new IllegalStateException(
String.format(
"Data change record shouldn't use READ operation, the the record is %s.",
changeRecord));
}
}
}
@Override
public List<SourceRecord> formatMessageTimestamp(Collection<SourceRecord> snapshotRecords) {
return snapshotRecords.stream()
.map(
record -> {
Envelope envelope = Envelope.fromSchema(record.valueSchema());
Struct value = (Struct) record.value();
Struct updateAfter = value.getStruct(Envelope.FieldName.AFTER);
// set message timestamp (source.ts_ms) to 0L
Struct source = value.getStruct(Envelope.FieldName.SOURCE);
source.put(Envelope.FieldName.TIMESTAMP, 0L);View on GitHub (pinned to cf67b549a7)
Solutions
- Check that incremental-snapshot (READ events) is not enabled in a way that leaks into the stream phase; align Debezium properties with the connector's expectations.
- Verify Debezium connector version compatibility with the SeaTunnel CDC connector version.
- Inspect the offending record (printed in the message) to see which table/operation produced the READ event and whether the source emitted it unexpectedly.
- Upgrade connector-cdc-base; known fixes adjusted event routing between snapshot and incremental phases.
Example fix
// before: buffer rewrite assumes only DML ops
switch (op) {
case READ: throw new IllegalStateException(...);
}
// after: treat READ as an upsert (insert) at buffer level
case READ:
case INSERT:
outputBuffer.put(key, record);
break; Defensive patterns
Strategy: validation
Validate before calling
// validate op before buffering
if (record.getOperation() == Operation.READ) {
log.warn("READ event in incremental phase; route to snapshot handling");
} Try / catch
try {
fetcherContext.rewriteOutputBuffer(buffer, key, changeRecord);
} catch (IllegalStateException e) {
if (e.getMessage().contains("READ operation")) { /* handle snapshot-event leak */ }
} Prevention
- Keep Debezium and connector-cdc versions compatible.
- Do not enable Debezium incremental-snapshot signaling alongside SeaTunnel's own snapshot logic.
- Test schema-change and snapshot-to-stream handoff paths before production.
When it happens
Trigger: A data change event with operation READ (from Debezium's op=r or a snapshot event) reaches the incremental fetcher's output-buffer rewrite path, which handles INSERT/UPDATE/DELETE only.
Common situations: Connector bug where snapshot records leak into the incremental phase; Debezium signaling/incremental snapshot mode emitting READ events during streaming; custom fetcher configuration mixing snapshot and stream events; version mismatch between Debezium and the SeaTunnel CDC connector.
Understand the failure class
Background: "invalid response format", "malformed payload", "missing data field": when an API returns 200 but the response shape is wrong — this error's family across 23 libraries.
Related errors
- Unable to instantiate the database history class " + config.
- The table changes should only have one element
- Unknown table change type:
- should not call here, error
- Failed to authenticate to the MySQL database at <hostname>:<
AI-assisted analysis of apache/seatunnel@cf67b549a7 (2026-09-10).
Data as JSON: /api/errors/219b0c47a306e867.
Report an issue: GitHub.