apache/seatunnel · error · SQLException

No LSN found for timestamp %d (%s)

Error message

No LSN found for timestamp %d (%s)

What it means

SqlServerUtils.timestampToLsn queries sys.fn_full_db_backup / LSN mapping via a prepared statement and expects at least one row matching the given timestamp. When the ResultSet is empty it throws a SQLException indicating no LSN exists for that timestamp, so a timestamp-based starting offset cannot be computed.

Source

Thrown at seatunnel-connectors-v2/connector-cdc/connector-cdc-sqlserver/src/main/java/org/apache/seatunnel/connectors/seatunnel/cdc/sqlserver/utils/SqlServerUtils.java:314

    public static LsnOffset timestampToLsn(
            SqlServerConnection connection, long timestampMs, String serverTimeZone) {
        try {
            String effectiveServerTimeZone =
                    serverTimeZone == null ? TimeZone.getDefault().getID() : serverTimeZone;
            String sql =
                    "SELECT sys.fn_cdc_map_time_to_lsn('smallest greater than or equal', ?) AS lsn";

            return connection.prepareQueryAndMap(
                    sql,
                    ps -> {
                        Timestamp timestamp = new Timestamp(timestampMs);
                        Calendar calendar =
                                Calendar.getInstance(TimeZone.getTimeZone(effectiveServerTimeZone));
                        ps.setTimestamp(1, timestamp, calendar);
                    },
                    rs -> {
                        if (!rs.next()) {
                            throw new SQLException(
                                    String.format(
                                            "No LSN found for timestamp %d (%s)",
                                            timestampMs, new Timestamp(timestampMs)));
                        }
                        byte[] lsnBytes = rs.getBytes("lsn");
                        if (lsnBytes == null) {
                            throw new SQLException(
                                    String.format(
                                            "LSN is null for timestamp %d (%s). "
                                                    + "This may indicate that CDC is not enabled or the timestamp is too old.",
                                            timestampMs, new java.sql.Timestamp(timestampMs)));
                        }
                        Lsn lsn = Lsn.valueOf(lsnBytes);
                        log.info(
                                "Converted timestamp {} ({}) to LSN: {}",
                                timestampMs,
                                new Timestamp(timestampMs),
                                lsn);

View on GitHub (pinned to cf67b549a7)

Solutions

  1. Choose a startup timestamp within the CDC/transaction-log retention window
  2. Verify CDC is enabled on the database/table and the capture instance exists (sys.cdc_databases, sys.cdc_tables)
  3. Enable retention or take a fresh full backup so LSN boundaries cover the timestamp
  4. Check effectiveServerTimeZone matches the SQL Server host time zone so the timestamp maps to the right log range

Example fix

// before
SqlServerUtils.timestampToLsn(conn, 0L, "UTC"); // timestamp before CDC enabled
// after
long ts = Timestamp.valueOf("2024-01-15 10:00:00").getTime(); // within CDC retention
SqlServerUtils.timestampToLsn(conn, ts, "UTC");
Defensive patterns

Strategy: validation

Validate before calling

// verify timestamp falls inside CDC retention before starting the job
Timestamp oldest = null;
try (Statement st = conn.createStatement();
     ResultSet rs = st.executeQuery("SELECT MIN(start_lsn) FROM cdc.lsn_time_mapping")) {
    if (rs.next()) oldest = sysLsnToTimestamp(rs.getBytes(1));
}
if (oldest == null || requestedTs.before(oldest)) {
    throw new IllegalArgumentException("Timestamp predates CDC retention");
}

Try / catch

try {
    LsnOffset off = SqlServerUtils.timestampToLsn(conn, tsMs, tz);
} catch (SeaTunnelException | SQLException e) {
    // fall back to latest LSN or abort with clear user guidance
}

Prevention

When it happens

Trigger: Calling timestampToLsn(ms) for a timestamp earlier than the oldest LSN retained by the transaction log or before CDC was enabled; the query returns zero rows and rs.next() is false.

Common situations: User sets startup.mode=timestamp with a date predating CDC retention; log truncation removed old LSNs; server time zone mismatch shifts the timestamp outside the mapped range.

Understand the failure class

Background: Record Not Found Errors: "not found", RecordNotFound, and "was not found" — what they mean and how to fix them — this error's family across 28 libraries.

Related errors


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