apache/iceberg · error · IllegalArgumentException

Cannot satisfy time filters: time range may include expired…

Error message

Cannot satisfy time filters: time range may include expired snapshots

What it means

ScanSummary.build throws IllegalArgumentException when the requested time range includes the oldest known snapshot but starts before that snapshot's timestamp: snapshots may have been expired, so results for the range would be unreliable/incomplete. Iceberg refuses to return partial summary data silently.

Solutions

  1. Narrow the time range to start at or after the oldest retained snapshot's timestamp.
  2. Disable/relax snapshot expiration or retain older snapshots if full-range summaries are needed.
  3. Catch IllegalArgumentException and surface 'results unavailable due to expiration' to users.

Example fix

// before
ScanSummary.filesAddedSinceTime(table, startTimeOfExpiredSnapshot);
// after
long oldest = table.currentSnapshot() ... oldest retained snapshot timestampMillis();
ScanSummary.filesAddedSinceTime(table, Math.max(startTime, oldest));
Defensive patterns

Strategy: try-catch

Validate before calling

Snapshot oldest = Iterables.getFirst(table.snapshots(), null);
if (oldest != null && rangeStart < oldest.timestampMillis()) { /* range may include expired snapshots */ }

Try / catch

try { summary = ScanSummary.build(...); } catch (IllegalArgumentException e) { /* narrow time range or report unreliability */ }

Prevention

When it happens

Trigger: Calling ScanSummary with time filters (e.g. snapshot summaries by made-current time) where minTimestamp < oldestSnapshot.timestampMillis() and the oldest snapshot is itself inside the range.

Common situations: See trigger scenarios.

Understand the failure class

Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.

Related errors


AI-assisted analysis of apache/iceberg@86d9c8fc54 (2026-09-12). Data as JSON: /api/errors/28dc713b03bdec1e. Report an issue: GitHub.

Appendix: source

Thrown at core/src/main/java/org/apache/iceberg/ScanSummary.java:191

        for (Map.Entry<Long, Long> entry : snapshotTimestamps.entrySet()) {
          long snapshotId = entry.getKey();
          long timestamp = entry.getValue();

          if (timestamp < oldestSnapshot.timestampMillis()) {
            oldestSnapshot = ops.current().snapshot(snapshotId);
          }

          if (timestamp >= minTimestamp && timestamp <= maxTimestamp) {
            snapshotsInTimeRange.add(snapshotId);
          }
        }

        // if oldest known snapshot is in the range, then there may be an expired snapshot that has
        // been removed that matched the range. because the timestamp of that snapshot is unknown,
        // it can't be included in the results and the results are not reliable.
        if (snapshotsInTimeRange.contains(oldestSnapshot.snapshotId())
            && minTimestamp < oldestSnapshot.timestampMillis()) {
          throw new IllegalArgumentException(
              "Cannot satisfy time filters: time range may include expired snapshots");
        }

        // filter down to the set of manifest files that were added after the start of the
        // time range. manifests after the end of the time range must be included because
        // compaction may create a manifest after the time range that includes files added in the
        // range.
        manifests =
            Iterables.filter(
                manifests,
                manifest -> {
                  if (manifest.snapshotId() == null) {
                    return true; // can't tell when the manifest was written, so it may contain
                    // matches
                  }

                  Long timestamp = snapshotTimestamps.get(manifest.snapshotId());
                  // if the timestamp is null, then its snapshot has expired. the check for the

View on GitHub (pinned to 86d9c8fc54)