{"record":{"id":"3f4f553c93f05703","repo":"apache/seatunnel","slug":"the-connector-is-trying-to-read-binlog-starting-at","errorCode":null,"errorMessage":"The connector is trying to read binlog starting at ${mySqlOffsetContext.getSourceInfo()}, but this is no longer available on the server. Reconfigure the connector to use a snapshot when needed.","messagePattern":"The connector is trying to read binlog starting at (.+?), but this is no longer available on the server\\. Reconfigure the connector to use a snapshot when needed\\.","errorType":"exception","errorClass":"IllegalStateException","httpStatus":null,"severity":"critical","filePath":"seatunnel-connectors-v2/connector-cdc/connector-cdc-mysql/src/main/java/org/apache/seatunnel/connectors/seatunnel/cdc/mysql/source/reader/fetch/MySqlSourceFetchTaskContext.java","lineNumber":293,"sourceCode":"    }\n\n    @Override\n    public Offset getStreamOffset(SourceRecord sourceRecord) {\n        return MySqlUtils.getBinlogPosition(sourceRecord);\n    }\n\n    /** Loads the connector's persistent offset (if present) via the given loader. */\n    private MySqlOffsetContext loadStartingOffsetState(\n            MySqlOffsetContext.Loader loader, SourceSplitBase mySqlSplit) {\n        Offset offset =\n                mySqlSplit.isSnapshotSplit()\n                        ? BinlogOffset.INITIAL_OFFSET\n                        : getInitOffset(mySqlSplit);\n        LOG.info(\"mysql cdc start at {}\", offset);\n        MySqlOffsetContext mySqlOffsetContext = loader.load(offset.getOffset());\n\n        if (!isBinlogAvailable(mySqlOffsetContext)) {\n            throw new IllegalStateException(\n                    \"The connector is trying to read binlog starting at \"\n                            + mySqlOffsetContext.getSourceInfo()\n                            + \", but this is no longer \"\n                            + \"available on the server. Reconfigure the connector to use a snapshot when needed.\");\n        }\n        return mySqlOffsetContext;\n    }\n\n    private Offset getInitOffset(SourceSplitBase mySqlSplit) {\n        StartupMode startupMode = getSourceConfig().getStartupConfig().getStartupMode();\n        Offset splitStartupOffset = mySqlSplit.asIncrementalSplit().getStartupOffset();\n        if (shouldResolveTimestampStartupOffset(startupMode, splitStartupOffset)) {\n            long timestamp = getSourceConfig().getStartupConfig().getTimestamp();\n            try (JdbcConnection jdbcConnection =\n                    getDataSourceDialect().openJdbcConnection(getSourceConfig())) {\n                return findBinlogOffsetBytimestamp(jdbcConnection, binaryLogClient, timestamp);\n            } catch (Exception e) {\n                throw new SeaTunnelException(e);","sourceCodeStart":275,"sourceCodeEnd":311,"githubUrl":"https://github.com/apache/seatunnel/blob/cf67b549a7a6c35fa0beb12d83c62892427ea919/seatunnel-connectors-v2/connector-cdc/connector-cdc-mysql/src/main/java/org/apache/seatunnel/connectors/seatunnel/cdc/mysql/source/reader/fetch/MySqlSourceFetchTaskContext.java#L275-L311","documentation":"When configuring a source fetch task, loadStartingOffsetState checks isBinlogAvailable: if the restored/configured binlog offset (from checkpoint state or startup config) is older than the server's earliest retained binlog, the required binlog has been purged. It throws IllegalStateException telling the user to restart with a snapshot.","triggerScenarios":"MySqlSourceFetchTaskContext.configure -> loadStartingOffsetState with a MySqlOffsetContext whose starting source info (file/pos/GTID) is no longer present on the server because binlogs expired (binlog_expire_logs_seconds/expire_logs_days) or RESET MASTER was run.","commonSituations":"Job paused/failing for days while MySQL purged old binlogs; restoring from an old checkpoint/savepoint; user supplied a very old specific-offset.file/pos or gtid-set that predates retention; replica promoted without the needed binlogs.","solutions":["Set startup.mode='initial' (or restart without saved state) to take a fresh snapshot and then continue from binlog","Increase MySQL retention (binlog_expire_logs_seconds / expire_logs_days) so outages don't outlive binlogs","Point to a still-available offset: pick the server's earliest existing binlog file via SHOW BINARY LOGS and use it as specific-offset.file/pos","If GTID-based, verify the gtid-set is still within the server's gtid_executed/purged state; otherwise snapshot again"],"exampleFix":"// before\nstartup {\n  mode = \"specific\"\n  specific-offset.file = \"mysql-bin.000001\"\n  specific-offset.pos = 4\n}\n// after\nstartup { mode = \"initial\" }","handlingStrategy":"fallback","validationCode":"// check offset availability before resuming\nSHOW BINARY LOGS; -- confirm your saved specific-offset.file (or GTID set) still exists on the server","typeGuard":null,"tryCatchPattern":"try {\n    startFromSavedOffset();\n} catch (IllegalStateException e) {\n    LOG.warn(\"Binlog no longer available; falling back to initial snapshot: {}\", e.getMessage());\n    restartWithStartupModeInitial();\n}","preventionTips":["Raise MySQL binlog retention (binlog_expire_logs_seconds) beyond worst-case outage length","Monitor job health so outages are fixed before purging catches up","Store checkpoints/savepoints and validate offset availability before restoring","Prefer GTID-based offsets with consistent replicas to reduce purged-binlog windows"],"tags":["mysql","binlog","cdc","data-loss"],"backgroundTag":"binlog-purged-unavailable","analyzedSha":"cf67b549a7a6c35fa0beb12d83c62892427ea919","analyzedAt":"2026-09-10T21:44:55.265Z","contentChangedAt":"2026-09-10T21:44:55.265Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}