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
- Enable CDC (sys.sp_cdc_enable_db / sys.sp_cdc_enable_table) on the target database and tables
- Pick a timestamp inside the CDC retention period (check sys.cdc_change_tracking or cdc.lsn_time_mapping)
- Increase retention / ensure the log is not truncated past the requested time
- 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
- Verify is_cdc_enabled=1 for the database and tables are tracked before timestamp startup
- Confirm cdc.lsn_time_mapping has entries near the requested time
- Keep CDC cleanup jobs from purging data older than your expected restart window
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
- No LSN found for timestamp %d (%s)
- Failed to convert timestamp %d (%s) to LSN: %s
- Invalid LSN format: %s. Expected format: 00000027:00000a80:0
- Read the binlog offset error
- not supported create new Offset by filename and position.
AI-assisted analysis of apache/seatunnel@cf67b549a7 (2026-09-10).
Data as JSON: /api/errors/bf5759069ab0ca3b.
Report an issue: GitHub.