apache/seatunnel · error · SQLException

LSN is null for timestamp %d (%s). This may indicate that CD

Error message

LSN is null for timestamp %d (%s). This may indicate that CDC is not enabled or the timestamp is too old.

What it means

timestampToLsn found a row for the timestamp but the returned lsn column is NULL. This means the mapping query produced no usable LSN — typically CDC metadata is missing or the requested time predates retained log data. The library fails fast because a null LSN cannot become an LsnOffset.

Source

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

            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);
                        return LsnOffset.timestampBoundary(lsn.toString());
                    });
        } catch (SQLException e) {
            throw new SeaTunnelException(
                    String.format(
                            "Failed to convert timestamp %d (%s) to LSN: %s",
                            timestampMs, new Timestamp(timestampMs), e.getMessage()),

View on GitHub (pinned to cf67b549a7)

Solutions

  1. Enable CDC (sys.sp_cdc_enable_db / sys.sp_cdc_enable_table) on the target database and tables
  2. Pick a timestamp inside the CDC retention period (check sys.cdc_change_tracking or cdc.lsn_time_mapping)
  3. Increase retention / ensure the log is not truncated past the requested time
  4. Verify the query targets the correct database — LSN mapping is per-database

Example fix

// before
long startTs = Instant.parse("2020-01-01T00:00:00Z").toEpochMilli(); // too old
// after
long startTs = System.currentTimeMillis() - Duration.ofHours(2).toMillis(); // inside retention
Defensive patterns

Strategy: validation

Validate before calling

SELECT name, is_cdc_enabled FROM sys.databases WHERE name = '<db>';
SELECT name FROM sys.tables WHERE is_tracked_by_cdc = 1;
-- ensure rows exist in cdc.lsn_time_mapping for the requested window

Try / catch

try {
    offset = SqlServerUtils.timestampToLsn(conn, tsMs, tz);
} catch (SeaTunnelException e) {
    if (e.getMessage().contains("LSN is null")) {
        // enable CDC or move the start timestamp forward
    }
}

Prevention

When it happens

Trigger: Calling timestampToLsn when the capture instance exists but CDC is disabled, or the timestamp is older than the retained log/cdc tables, causing the LSN column to come back null.

Common situations: CDC disabled at database level after previously being enabled; log backup purged old LSNs; querying sys.fn_dblog-like mapping before the first CDC record.

Related errors


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