apache/seatunnel · error · IllegalStateException
The "before" field of ${op} operation is null, if you are us
Error message
The "before" field of ${op} operation is null, if you are using Debezium Postgres Connector, please check the Postgres table has been set REPLICA IDENTITY to FULL level. What it means
When decoding a Debezium UPDATE event, the converter needs the payload's 'before' image to emit the UPDATE_BEFORE row. If payload.before is missing or null, DebeziumJsonDeserializationSchema throws IllegalStateException via the REPLICA_IDENTITY_EXCEPTION template. For Postgres this means the table's REPLICA IDENTITY is not FULL, so the WAL change event carries no old row values.
Source
Thrown at seatunnel-formats/seatunnel-format-json/src/main/java/org/apache/seatunnel/format/json/debezium/DebeziumJsonDeserializationSchema.java:140
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);
if (tablePath != null) {
insert.setTableId(tablePath.toString());
}
if (tsNode != null) {
MetadataUtil.setEventTime(insert, tsNode.asLong());
}
out.collect(insert);
break;
case OP_UPDATE:
SeaTunnelRow before = debeziumRowConverter.parse(payload.get(DATA_BEFORE));
if (before == null) {
throw new IllegalStateException(
String.format(REPLICA_IDENTITY_EXCEPTION, "UPDATE"));
}
before.setRowKind(RowKind.UPDATE_BEFORE);
if (tablePath != null) {
before.setTableId(tablePath.toString());
}
if (tsNode != null) {
MetadataUtil.setEventTime(before, tsNode.asLong());
}
SeaTunnelRow after = debeziumRowConverter.parse(payload.get(DATA_AFTER));
after.setRowKind(RowKind.UPDATE_AFTER);
if (tablePath != null) {
after.setTableId(tablePath.toString());
}
if (tsNode != null) {
MetadataUtil.setEventTime(after, tsNode.asLong());View on GitHub (pinned to cf67b549a7)
Solutions
- Run ALTER TABLE <table> REPLICA IDENTITY FULL; on the source Postgres table
- Verify with SELECT relreplident FROM pg_class WHERE relname='<table>'; — it should show 'f' (FULL)
- If FULL is infeasible, configure the pipeline to skip UPDATE_BEFORE (e.g. handle only after-images downstream)
- For non-Postgres sources, inspect the Debezium connector config (converters/SMTs) for anything dropping the before field
Example fix
// psql, before capturing CDC ALTER TABLE my_table REPLICA IDENTITY FULL;
Defensive patterns
Strategy: validation
Validate before calling
-- pre-flight check on the source table SELECT relreplident FROM pg_class WHERE relname = 'my_table'; -- must be 'f'
Try / catch
try {
deserializer.deserialize(message, out);
} catch (IllegalStateException e) {
if (e.getMessage().contains("REPLICA IDENTITY")) {
log.error("Set REPLICA IDENTITY FULL on the source table and re-capture", e);
}
throw e;
} Prevention
- ALTER TABLE ... REPLICA IDENTITY FULL for all CDC-captured Postgres tables
- Verify relreplident='f' as part of deployment
- Document replica-identity requirements in runbooks
When it happens
Trigger: Consuming Debezium Postgres UPDATE events (op='u') where payload.get(DATA_BEFORE) returns null — i.e. the source table has default replica identity (DEFAULT or NOTHING).
Common situations: Postgres logical replication on tables never configured for FULL replica identity; tables whose primary key exists but replica identity is default; custom Debezium converters that drop the before-image.
Understand the failure class
Background: "missing required argument" and "the following required arguments were not provided": what required-argument errors mean and how to fix them — this error's family across 20 libraries.
Related errors
- Table ${tableId} does not have a full replica identity, plea
- The "before" field of %s operation message is null, if you a
- Cannot determine REPLICA IDENTITY information for table '{}'
- Unable to instantiate the database history class " + config.
- Data change record shouldn't use READ operation, the the rec
AI-assisted analysis of apache/seatunnel@cf67b549a7 (2026-09-10).
Data as JSON: /api/errors/57231339066b195f.
Report an issue: GitHub.