apache/seatunnel · warning

Out-of-range offset while polling table {}; resetting trunca

Error message

Out-of-range offset while polling table {}; resetting truncated buckets to earliest

What it means

While fetching records, the Fluss source reader may receive a FetchException whose cause is LogOffsetOutOfRangeException, meaning a subscribed bucket's stored offset was removed by log retention and polling is now out of range. The reader logs this warning, resets every truncated bucket (one whose start offset is beyond the requested offset) to its earliest available offset, and retries on the next fetch(). If no bucket was actually truncated, the original exception is rethrown because the out-of-range error is not a retention issue.

Source

Thrown at seatunnel-connectors-v2/connector-fluss/src/main/java/org/apache/seatunnel/connectors/seatunnel/fluss/source/FlussSourceSplitReader.java:123

    }

    @Override
    public RecordsWithSplitIds<FlussRecord> fetch() throws IOException {
        Map<String, Collection<FlussRecord>> recordsBySplit = new HashMap<>();
        Set<String> finishedSplits = new HashSet<>();

        TableScan scan = tableScan;
        if (scan != null) {
            ScanRecords scanRecords = null;
            try {
                scanRecords = scan.logScanner.poll(pollTimeout);
            } catch (FetchException e) {
                if (!(e.getCause() instanceof LogOffsetOutOfRangeException)) {
                    throw e;
                }
                // A subscribed offset was discarded by retention. Reset the bucket(s) now behind
                // their earliest and retry on the next fetch().
                log.warn(
                        "Out-of-range offset while polling table {}; resetting truncated buckets to earliest",
                        scan.tablePath.getFullName(),
                        e);
                if (!resetTruncatedBuckets(scan)) {
                    // Nothing was behind its earliest, so this out-of-range is not a recoverable
                    // front-side retention truncation. Fail with the original cause
                    // instead of re-polling and throwing the same exception forever.
                    throw e;
                }
            }
            if (scanRecords != null) {
                for (TableBucket bucket : scanRecords.buckets()) {
                    BucketReader reader = assigned.get(bucket);
                    if (reader == null || reader.done) {
                        // Unknown bucket, or a bucket already finished but still subscribed.
                        continue;
                    }
                    FlussSourceSplit split = reader.split;

View on GitHub (pinned to cf67b549a7)

Solutions

  1. Accept the automatic reset: the reader skips to the earliest available offset and continues — be aware data older than retention is lost.
  2. If the reset finds nothing truncated and the job fails, verify the offset actually exists (not a corrupted/stale checkpoint) and remove or update the saved state.
  3. Adjust Fluss table retention so log segments outlive expected job downtime to avoid silent data skipping.
  4. Re-run or backfill the missed window from an upstream source if the skipped data matters.
Defensive patterns

Strategy: try-catch

Validate before calling

// before starting, ensure stored offsets still exist within retention
long earliest = admin.getEarliestOffset(tablePath, bucketId);
long latest = admin.getLatestOffset(tablePath, bucketId);
if (savedOffset < earliest) {
    log.warn("Saved offset {} is below earliest {} for bucket {} — data will be skipped",
             savedOffset, earliest, bucketId);
}

Try / catch

try {
    reader.fetch();
} catch (FetchException e) {
    if (e.getCause() instanceof LogOffsetOutOfRangeException) {
        // retention truncated the logs; reader auto-resets truncated buckets to earliest.
        // Alert/record here: data between savedOffset and earliest is lost.
    } else {
        throw e;
    }
}

Prevention

When it happens

Trigger: fetch() polling a Fluss table when retention has deleted log segments covering the reader's stored offset — typically after a long pause, checkpoint restore from a stale state, or aggressive table retention settings. A FetchException with LogOffsetOutOfRangeException cause triggers the reset path.

Common situations: Job stopped or failed for days and restarted from old offsets; retention configured shorter than expected downtime; bucket data compacted/deleted by Fluss while offsets persisted in a checkpoint.

Related errors


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