apache/seatunnel · error · IllegalStateException

The "before" field of %s operation message is null, if you a

Error message

The "before" field of %s operation message is null, if you are using Ogg Postgres Connector, please check the Postgres table has been set REPLICA IDENTITY to FULL level.

What it means

For an Ogg UPDATE event, both the before and after images are required (SeaTunnel emits UPDATE_BEFORE/UPDATE_AFTER rows). When the JSON message lacks a non-null "before" (DATA_BEFORE) node, deserializeMessage throws IllegalStateException with REPLICA_IDENTITY_EXCEPTION telling the user to set REPLICA IDENTITY FULL — because the source database isn't publishing the old row image.

Source

Thrown at seatunnel-formats/seatunnel-format-json/src/main/java/org/apache/seatunnel/format/json/ogg/OggJsonDeserializationSchema.java:183

            }
            switch (op) {
                case OP_INSERT:
                    // Gets the data for the INSERT operation
                    JsonNode dataInsert = jsonNode.get(DATA_AFTER);
                    SeaTunnelRow row = convertJsonNode(dataInsert);
                    if (tablePath != null) {
                        row.setTableId(tablePath.toString());
                    }
                    if (tsNode != null) {
                        MetadataUtil.setEventTime(row, ts);
                    }
                    out.collect(row);
                    break;
                case OP_UPDATE:
                    JsonNode dataBefore = jsonNode.get(DATA_BEFORE);
                    // Modify Operation Data cannot be empty before modification
                    if (dataBefore == null || dataBefore.isNull()) {
                        throw new IllegalStateException(
                                String.format(REPLICA_IDENTITY_EXCEPTION, "UPDATE"));
                    }
                    JsonNode dataAfter = jsonNode.get(DATA_AFTER);
                    // Gets the data for the UPDATE BEFORE operation
                    SeaTunnelRow before = convertJsonNode(dataBefore);
                    // Gets the data for the UPDATE AFTER operation
                    SeaTunnelRow after = convertJsonNode(dataAfter);
                    before.setRowKind(RowKind.UPDATE_BEFORE);
                    if (tablePath != null) {
                        before.setTableId(tablePath.toString());
                    }
                    if (tsNode != null) {
                        MetadataUtil.setEventTime(before, ts);
                    }

                    after.setRowKind(RowKind.UPDATE_AFTER);
                    if (tablePath != null) {
                        after.setTableId(tablePath.toString());

View on GitHub (pinned to cf67b549a7)

Solutions

  1. For Postgres: run ALTER TABLE <table> REPLICA IDENTITY FULL; for Oracle: enable supplemental log data (ALL) at table level
  2. Adjust Ogg/extract configuration to include before-images in the trail records
  3. If before-images cannot be enabled, skip or down-convert updates (e.g. treat as insert-only) with custom handling
  4. Verify the actual Ogg JSON payload has a populated "before" object for updates

Example fix

// before
ALTER TABLE mytable REPLICA IDENTITY DEFAULT;
// after
ALTER TABLE mytable REPLICA IDENTITY FULL;
Defensive patterns

Strategy: validation

Validate before calling

// verify before-images are published (Postgres)
// SELECT relreplident FROM pg_class WHERE relname = 'mytable'; -- must be 'f' (FULL)
JsonNode before = root.get("before");
if (before == null || before.isNull()) {
    log.error("UPDATE missing before-image; enable REPLICA IDENTITY FULL");
}

Try / catch

try {
    schema.deserialize(message, out);
} catch (IllegalStateException e) {
    log.error("Replica identity misconfigured: {}", e.getMessage());
    throw e;
}

Prevention

When it happens

Trigger: deserialize → deserializeMessage handles case OP_UPDATE; jsonNode.get(DATA_BEFORE) returns null or an isNull() node because the upstream Ogg message for UPDATE contains only the "after" data.

Common situations: Oracle via Ogg without supplemental logging of all columns; Ogg Postgres connector where the table's REPLICA IDENTITY is DEFAULT (only PK in before image) or NOTHING; tables without primary keys; Ogg parameterization omitting before-images.

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


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