apache/seatunnel · error · RuntimeException

Convert timestamp to LSN offset error

Error message

Convert timestamp to LSN offset error

What it means

Thrown by LsnOffsetFactory.timestamp() when converting a user-supplied timestamp to an LSN via SqlServerUtils.timestampToLsn() fails — either the JDBC call or the conversion (e.g. the timestamp predates the retained CDC log). The RuntimeException wraps the underlying cause.

Source

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

    public Offset specific(Map<String, String> offset) {
        return LsnOffset.valueOf(offset);
    }

    @Override
    public Offset specific(String filename, Long position) {
        throw new UnsupportedOperationException(
                "not supported create new Offset by filename and position.");
    }

    @Override
    public Offset timestamp(long timestamp) {
        try (JdbcConnection jdbcConnection = dialect.openJdbcConnection(sourceConfig)) {
            return SqlServerUtils.timestampToLsn(
                    (SqlServerConnection) jdbcConnection,
                    timestamp,
                    sourceConfig.getServerTimeZone());
        } catch (Exception e) {
            throw new RuntimeException("Convert timestamp to LSN offset error", e);
        }
    }
}

View on GitHub (pinned to cf67b549a7)

Solutions

  1. Pick a timestamp within the CDC retention window (check sys.cdc change-table min LSN)
  2. Align the configured server time zone with the actual SQL Server time zone
  3. Inspect the wrapped exception for connection vs conversion errors
  4. Fall back to latest() or snapshot mode if no valid LSN exists for the timestamp
  5. Extend CDC retention (capture job retention period) if historical starts are needed

Example fix

// before
long ts = Instant.parse("2023-01-01T00:00:00Z").toEpochMilli(); // likely outside retention
Offset o = factory.timestamp(ts);
// after
Instant ts = Instant.now().minus(Duration.ofHours(1)); // within retention
Offset o = factory.timestamp(ts.toEpochMilli());
Defensive patterns

Strategy: validation

Validate before calling

// ensure the timestamp maps to a retained LSN before calling timestamp()
ResultSet rs = c.createStatement().executeQuery(
    "SELECT sys.fn_cdc_map_time_to_lsn('largest less than or equal', ?)");
rs.setTimestamp(1, new Timestamp(userTimestamp));
rs.next();
if (rs.getBigDecimal(1) == null) {
    throw new IllegalStateException("timestamp outside CDC retention window");
}

Try / catch

try {
    offset = offsetFactory.timestamp(ts);
} catch (RuntimeException e) {
    LOG.warn("timestamp->LSN conversion failed; falling back to latest()", e);
    offset = offsetFactory.latest();
}

Prevention

When it happens

Trigger: Calling timestamp(ts) where the JDBC connection fails, the timestamp is outside the CDC retention window (no LSN maps to it), or the timestamp is invalid relative to the configured server time zone.

Common situations: Incremental start from a timestamp older than CDC retention (rows cleaned by the capture job); time zone mismatch between user timestamp and sourceConfig.getServerTimeZone(); connection failure at startup.

Related errors


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