apache/seatunnel · error · RuntimeException

Read the binlog offset error

Error message

Read the binlog offset error

What it means

LsnOffsetFactory.latest() opens a JDBC connection to PostgreSQL to read the current LSN (write-ahead-log position) used as the newest offset. If the connection or the currentLSN query fails for any reason it wraps the exception in a RuntimeException with message 'Read the binlog offset error' (Postgres has no binlog; the message is inherited from MySQL-CDC phrasing).

Source

Thrown at seatunnel-connectors-v2/connector-cdc/connector-cdc-postgres/src/main/java/org/apache/seatunnel/connectors/seatunnel/cdc/postgres/source/offset/LsnOffsetFactory.java:69

        this.dialect = dialect;
    }

    @Override
    public Offset earliest() {
        return LsnOffset.INITIAL_OFFSET;
    }

    @Override
    public Offset neverStop() {
        return LsnOffset.NO_STOPPING_OFFSET;
    }

    @Override
    public Offset latest() {
        try (JdbcConnection jdbcConnection = dialect.openJdbcConnection(sourceConfig)) {
            return PostgresUtils.currentLsn((PostgresConnection) jdbcConnection);
        } catch (Exception e) {
            throw new RuntimeException("Read the binlog offset error", e);
        }
    }

    @Override
    public Offset committedOffset() {
        String slotName = sourceConfig.getDbzConfiguration().getString("slot.name");
        try (JdbcConnection jdbcConnection = dialect.openJdbcConnection(sourceConfig)) {
            try (PreparedStatement statement =
                    jdbcConnection
                            .connection()
                            .prepareStatement(
                                    "SELECT confirmed_flush_lsn::text, active_pid FROM pg_replication_slots WHERE slot_name = ?")) {
                statement.setString(1, slotName);
                try (ResultSet resultSet = statement.executeQuery()) {
                    return readCommittedOffset(resultSet, slotName);
                }
            }
        } catch (SeaTunnelRuntimeException e) {

View on GitHub (pinned to cf67b549a7)

Solutions

  1. Verify JDBC connectivity with the same credentials via psql or a plain JDBC test.
  2. Confirm you are connecting to the primary node (LSN reads require it).
  3. Check network/firewall rules between the SeaTunnel worker and PostgreSQL.
  4. Inspect the wrapped cause exception for the underlying SQL/connection error.
Defensive patterns

Strategy: retry

Validate before calling

// Validate connectivity before starting the job
try (Connection c = DriverManager.getConnection(jdbcUrl, user, pass)) {
    c.createStatement().executeQuery("SELECT pg_current_wal_lsn()");
}

Try / catch

try {
    Offset o = factory.latest();
} catch (RuntimeException e) {
    // inspect e.getCause() for SQL/connection error, retry with backoff
}

Prevention

When it happens

Trigger: Calling latest() during split enumeration/startup when the JDBC connection cannot be opened, credentials are wrong, the host is unreachable, or `PostgresUtils.currentLsn` fails (e.g. non-primary node or pg_current_wal_lsn() unavailable).

Common situations: Wrong hostname/port/database in source config; firewall or VPC blocking the DB port; read-replica used where LSN functions are restricted; expired credentials.

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/4f207b0ecac005da. Report an issue: GitHub.