apache/seatunnel · error · ConnectException

restart_lsn could be found

Error message

restart_lsn could be found

What it means

parseRestartLsn reads restart_lsn from pg_replication_slots for the slot and throws this ConnectException if the column read fails (note the message omits 'not' — it means restart_lsn could NOT be found). restart_lsn is required as the fallback position when confirmed_flush_lsn is unavailable, so its absence is fatal.

Source

Thrown at seatunnel-connectors-v2/connector-cdc/connector-cdc-opengauss/src/main/java/io/debezium/connector/postgresql/connection/PostgresConnection.java:403

            LOGGER.info("unable to find confirmed_flushed_lsn, falling back to restart_lsn");
            try {
                confirmedFlushedLsn =
                        tryParseLsn(slotName, pluginName, database, rs, "restart_lsn");
            } catch (SQLException e2) {
                throw new ConnectException(
                        "Neither confirmed_flush_lsn nor restart_lsn could be found");
            }
        }

        return confirmedFlushedLsn;
    }

    private Lsn parseRestartLsn(String slotName, String pluginName, String database, ResultSet rs) {
        Lsn restartLsn = null;
        try {
            restartLsn = tryParseLsn(slotName, pluginName, database, rs, "restart_lsn");
        } catch (SQLException e) {
            throw new ConnectException("restart_lsn could be found");
        }

        return restartLsn;
    }

    private Lsn tryParseLsn(
            String slotName, String pluginName, String database, ResultSet rs, String column)
            throws ConnectException, SQLException {
        Lsn lsn = null;

        String lsnStr = rs.getString(column);
        if (lsnStr == null) {
            return null;
        }
        try {
            lsn = Lsn.valueOf(lsnStr);
        } catch (Exception e) {
            throw new ConnectException(

View on GitHub (pinned to cf67b549a7)

Solutions

  1. Confirm the slot still exists and exposes restart_lsn: SELECT slot_name, restart_lsn FROM pg_replication_slots WHERE slot_name = '<slot>';
  2. Grant the connector user REPLICATION / read access to pg_catalog.pg_replication_slots.
  3. Stop external tooling from dropping the slot while the connector starts.
  4. Ensure wal_level=logical and that the slot was created as a logical (not physical) slot, since restart_lsn semantics differ.

Example fix

// before: unprivileged user triggers SQLException on restart_lsn
-- after
ALTER USER cdc_user WITH REPLICATION;
GRANT SELECT ON pg_catalog.pg_replication_slots TO cdc_user;
Defensive patterns

Strategy: validation

Validate before calling

SELECT restart_lsn FROM pg_replication_slots WHERE slot_name = 'seatunnel_slot' AND slot_type = 'logical'; -- row must exist with a non-null restart_lsn

Try / catch

try {
    connection.restartLsn(slotName);
} catch (ConnectException e) {
    // slot vanished or is unreadable: recreate before retry
}

Prevention

When it happens

Trigger: tryParseLsn's SELECT of restart_lsn throws SQLException for the slot row — the slot was dropped between queries, the user cannot read pg_replication_slots, or the column is absent on this server version.

Common situations: Monitoring/HA tooling removed the slot mid-startup; restricted DB user; older OpenGauss builds with a trimmed pg_replication_slots view.

Understand the failure class

Background: Database query failed: Internal Server Error 500s wrapping SQL, Prisma, and connection failures — what to check first — this error's family across 16 libraries.

Related errors


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