apache/seatunnel · critical · IllegalStateException

The connector is trying to read binlog starting at ${mySqlOf

Error message

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.

What it means

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.

Source

Thrown at seatunnel-connectors-v2/connector-cdc/connector-cdc-mysql/src/main/java/org/apache/seatunnel/connectors/seatunnel/cdc/mysql/source/reader/fetch/MySqlSourceFetchTaskContext.java:293

    }

    @Override
    public Offset getStreamOffset(SourceRecord sourceRecord) {
        return MySqlUtils.getBinlogPosition(sourceRecord);
    }

    /** Loads the connector's persistent offset (if present) via the given loader. */
    private MySqlOffsetContext loadStartingOffsetState(
            MySqlOffsetContext.Loader loader, SourceSplitBase mySqlSplit) {
        Offset offset =
                mySqlSplit.isSnapshotSplit()
                        ? BinlogOffset.INITIAL_OFFSET
                        : getInitOffset(mySqlSplit);
        LOG.info("mysql cdc start at {}", offset);
        MySqlOffsetContext mySqlOffsetContext = loader.load(offset.getOffset());

        if (!isBinlogAvailable(mySqlOffsetContext)) {
            throw new IllegalStateException(
                    "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.");
        }
        return mySqlOffsetContext;
    }

    private Offset getInitOffset(SourceSplitBase mySqlSplit) {
        StartupMode startupMode = getSourceConfig().getStartupConfig().getStartupMode();
        Offset splitStartupOffset = mySqlSplit.asIncrementalSplit().getStartupOffset();
        if (shouldResolveTimestampStartupOffset(startupMode, splitStartupOffset)) {
            long timestamp = getSourceConfig().getStartupConfig().getTimestamp();
            try (JdbcConnection jdbcConnection =
                    getDataSourceDialect().openJdbcConnection(getSourceConfig())) {
                return findBinlogOffsetBytimestamp(jdbcConnection, binaryLogClient, timestamp);
            } catch (Exception e) {
                throw new SeaTunnelException(e);

View on GitHub (pinned to cf67b549a7)

Solutions

  1. Set startup.mode='initial' (or restart without saved state) to take a fresh snapshot and then continue from binlog
  2. Increase MySQL retention (binlog_expire_logs_seconds / expire_logs_days) so outages don't outlive binlogs
  3. 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
  4. If GTID-based, verify the gtid-set is still within the server's gtid_executed/purged state; otherwise snapshot again

Example fix

// before
startup {
  mode = "specific"
  specific-offset.file = "mysql-bin.000001"
  specific-offset.pos = 4
}
// after
startup { mode = "initial" }
Defensive patterns

Strategy: fallback

Validate before calling

// check offset availability before resuming
SHOW BINARY LOGS; -- confirm your saved specific-offset.file (or GTID set) still exists on the server

Try / catch

try {
    startFromSavedOffset();
} catch (IllegalStateException e) {
    LOG.warn("Binlog no longer available; falling back to initial snapshot: {}", e.getMessage());
    restartWithStartupModeInitial();
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


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