apache/seatunnel · error · IllegalStateException

The restored committed-offset checkpoint does not contain it

Error message

The restored committed-offset checkpoint does not contain its startup offset

What it means

IncrementalSplitAssigner.createIncrementalSplit computes the start offset for a new incremental split as the minimum low-watermark offset across finished snapshot splits, falling back to the startup offset. When a job started in COMMITTED_OFFSET mode is restored from checkpoint and neither a computed minOffset nor a stored startupOffset exists, the saved state cannot reproduce the committed-offset startup position, so IllegalStateException is thrown.

Source

Thrown at seatunnel-connectors-v2/connector-cdc/connector-cdc-base/src/main/java/org/apache/seatunnel/connectors/cdc/base/source/enumerator/IncrementalSplitAssigner.java:293

                            split.getSplitStart(),
                            split.getSplitEnd(),
                            splitWatermark));
        }
        for (TableId tableId : capturedTables) {
            Offset watermark = tableWatermarks.get(tableId);
            if (minOffset == null || (watermark != null && watermark.isBefore(minOffset))) {
                minOffset = watermark;
                LOG.debug(
                        "Find the min offset {} of change log in table-watermarks {}",
                        watermark,
                        tableId);
            }
        }
        if (minOffset == null && startupOffset == null) {
            if (restoredFromCheckpoint
                    && sourceConfig.getStartupConfig().getStartupMode()
                            == StartupMode.COMMITTED_OFFSET) {
                throw new IllegalStateException(
                        "The restored committed-offset checkpoint does not contain its startup offset");
            }
            startupOffset = sourceConfig.getStartupConfig().getStartupOffset(offsetFactory);
        }
        Offset incrementalSplitStartOffset = minOffset != null ? minOffset : startupOffset;
        return new IncrementalSplit(
                String.format(INCREMENTAL_SPLIT_ID, index),
                capturedTables,
                incrementalSplitStartOffset,
                sourceConfig.getStopConfig().getStopOffset(offsetFactory),
                completedSnapshotSplitInfos,
                checkpointTables,
                historyTableChanges);
    }

    @VisibleForTesting
    void setSplitAssigned(boolean assigned) {
        this.splitAssigned = assigned;

View on GitHub (pinned to cf67b549a7)

Solutions

  1. Restart the job without restore (fresh run) so the committed offset is re-resolved from the database at startup
  2. Change startup.mode (e.g. to 'initial' or 'earliest') so a startup offset can always be derived on restore
  3. Use a checkpoint/savepoint created with a connector-cdc version that persists the startup offset
  4. Verify checkpoint files are not truncated/corrupted; re-take a savepoint from a healthy running job

Example fix

// before
"startup.mode" = "committed_offset"
// restore from old checkpoint lacking startup offset -> IllegalStateException
// after
"startup.mode" = "earliest"   // startup offset always derivable on restore
// or restart fresh with committed_offset
bin/seatunnel.sh --config job.conf
Defensive patterns

Strategy: fallback

Validate before calling

// before restore, confirm state carries a startup offset when mode is committed_offset
if (startupMode == StartupMode.COMMITTED_OFFSET && state.getStartupOffset() == null) {
    LOG.warn("Restored committed-offset state lacks startup offset; restart fresh instead of restoring");
}

Try / catch

try {
    split = assigner.createIncrementalSplit(...);
} catch (IllegalStateException e) {
    // fall back: restart job fresh or with a different startup.mode
}

Prevention

When it happens

Trigger: Restoring a CDC job whose startup.mode = committed_offset from a checkpoint that lacks the startup offset in the assigner state and has no incremental/finished splits providing a minOffset.

Common situations: Checkpoint/savepoint from an older connector version that did not persist the committed-offset startup position, restoring a state file that lost the startup offset, or committed_offset mode combined with corrupted checkpoint state.

Understand the failure class

Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.

Related errors


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