{"record":{"id":"bf5759069ab0ca3b","repo":"apache/seatunnel","slug":"lsn-is-null-for-timestamp-d-s-this-may-indica","errorCode":null,"errorMessage":"LSN is null for timestamp %d (%s). This may indicate that CDC is not enabled or the timestamp is too old.","messagePattern":"LSN is null for timestamp (.+?) \\((.+?)\\)\\. This may indicate that CDC is not enabled or the timestamp is too old\\.","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":321,"sourceCode":"\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);\n                        return LsnOffset.timestampBoundary(lsn.toString());\n                    });\n        } catch (SQLException e) {\n            throw new SeaTunnelException(\n                    String.format(\n                            \"Failed to convert timestamp %d (%s) to LSN: %s\",\n                            timestampMs, new Timestamp(timestampMs), e.getMessage()),","sourceCodeStart":303,"sourceCodeEnd":339,"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#L303-L339","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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"],"exampleFix":"// before\nlong startTs = Instant.parse(\"2020-01-01T00:00:00Z\").toEpochMilli(); // too old\n// after\nlong startTs = System.currentTimeMillis() - Duration.ofHours(2).toMillis(); // inside retention","handlingStrategy":"validation","validationCode":"SELECT name, is_cdc_enabled FROM sys.databases WHERE name = '<db>';\nSELECT name FROM sys.tables WHERE is_tracked_by_cdc = 1;\n-- ensure rows exist in cdc.lsn_time_mapping for the requested window","typeGuard":null,"tryCatchPattern":"try {\n    offset = SqlServerUtils.timestampToLsn(conn, tsMs, tz);\n} catch (SeaTunnelException e) {\n    if (e.getMessage().contains(\"LSN is null\")) {\n        // enable CDC or move the start timestamp forward\n    }\n}","preventionTips":["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"],"tags":["sqlserver","cdc","lsn","null"],"backgroundTag":"null-argument","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"}