{"record":{"id":"2840e9e8fdbf3873","repo":"apache/seatunnel","slug":"no-lsn-found-for-timestamp-d-s","errorCode":null,"errorMessage":"No LSN found for timestamp %d (%s)","messagePattern":"No LSN found for timestamp (.+?) \\((.+?)\\)","errorType":"exception","errorClass":"SQLException","httpStatus":null,"severity":"error","filePath":"seatunnel-connectors-v2/connector-cdc/connector-cdc-sqlserver/src/main/java/org/apache/seatunnel/connectors/seatunnel/cdc/sqlserver/utils/SqlServerUtils.java","lineNumber":314,"sourceCode":"    public static LsnOffset timestampToLsn(\n            SqlServerConnection connection, long timestampMs, String serverTimeZone) {\n        try {\n            String effectiveServerTimeZone =\n                    serverTimeZone == null ? TimeZone.getDefault().getID() : serverTimeZone;\n            String sql =\n                    \"SELECT sys.fn_cdc_map_time_to_lsn('smallest greater than or equal', ?) AS lsn\";\n\n            return connection.prepareQueryAndMap(\n                    sql,\n                    ps -> {\n                        Timestamp timestamp = new Timestamp(timestampMs);\n                        Calendar calendar =\n                                Calendar.getInstance(TimeZone.getTimeZone(effectiveServerTimeZone));\n                        ps.setTimestamp(1, timestamp, calendar);\n                    },\n                    rs -> {\n                        if (!rs.next()) {\n                            throw new SQLException(\n                                    String.format(\n                                            \"No LSN found for timestamp %d (%s)\",\n                                            timestampMs, new Timestamp(timestampMs)));\n                        }\n                        byte[] lsnBytes = rs.getBytes(\"lsn\");\n                        if (lsnBytes == null) {\n                            throw new SQLException(\n                                    String.format(\n                                            \"LSN is null for timestamp %d (%s). \"\n                                                    + \"This may indicate that CDC is not enabled or the timestamp is too old.\",\n                                            timestampMs, new java.sql.Timestamp(timestampMs)));\n                        }\n                        Lsn lsn = Lsn.valueOf(lsnBytes);\n                        log.info(\n                                \"Converted timestamp {} ({}) to LSN: {}\",\n                                timestampMs,\n                                new Timestamp(timestampMs),\n                                lsn);","sourceCodeStart":296,"sourceCodeEnd":332,"githubUrl":"https://github.com/apache/seatunnel/blob/cf67b549a7a6c35fa0beb12d83c62892427ea919/seatunnel-connectors-v2/connector-cdc/connector-cdc-sqlserver/src/main/java/org/apache/seatunnel/connectors/seatunnel/cdc/sqlserver/utils/SqlServerUtils.java#L296-L332","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Choose a startup timestamp within the CDC/transaction-log retention window","Verify CDC is enabled on the database/table and the capture instance exists (sys.cdc_databases, sys.cdc_tables)","Enable retention or take a fresh full backup so LSN boundaries cover the timestamp","Check effectiveServerTimeZone matches the SQL Server host time zone so the timestamp maps to the right log range"],"exampleFix":"// before\nSqlServerUtils.timestampToLsn(conn, 0L, \"UTC\"); // timestamp before CDC enabled\n// after\nlong ts = Timestamp.valueOf(\"2024-01-15 10:00:00\").getTime(); // within CDC retention\nSqlServerUtils.timestampToLsn(conn, ts, \"UTC\");","handlingStrategy":"validation","validationCode":"// verify timestamp falls inside CDC retention before starting the job\nTimestamp oldest = null;\ntry (Statement st = conn.createStatement();\n     ResultSet rs = st.executeQuery(\"SELECT MIN(start_lsn) FROM cdc.lsn_time_mapping\")) {\n    if (rs.next()) oldest = sysLsnToTimestamp(rs.getBytes(1));\n}\nif (oldest == null || requestedTs.before(oldest)) {\n    throw new IllegalArgumentException(\"Timestamp predates CDC retention\");\n}","typeGuard":null,"tryCatchPattern":"try {\n    LsnOffset off = SqlServerUtils.timestampToLsn(conn, tsMs, tz);\n} catch (SeaTunnelException | SQLException e) {\n    // fall back to latest LSN or abort with clear user guidance\n}","preventionTips":["Check cdc.lsn_time_mapping covers the requested time before using startup.mode=timestamp","Keep the SQL Server log retention long enough for restart timestamps","Set the server time zone option correctly in connector config","Prefer latest/initial startup modes unless a precise timestamp is required"],"tags":["sqlserver","cdc","lsn","timestamp"],"backgroundTag":"record-not-found","analyzedSha":"cf67b549a7a6c35fa0beb12d83c62892427ea919","analyzedAt":"2026-09-10T21:44:55.265Z","contentChangedAt":"2026-09-10T21:44:55.265Z","schemaVersion":2},"datasetVersion":"2026-09-14T11:17:12.474Z"}