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
- Narrow the time range to start at or after the oldest retained snapshot's timestamp.
- Disable/relax snapshot expiration or retain older snapshots if full-range summaries are needed.
- 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
- Clamp query ranges to the oldest retained snapshot timestamp
- Account for expireSnapshots retention policy in dashboards
- Preserve snapshots if historical summaries are required
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
- No timestamps can match filters:
- Cannot clean files incrementally when snapshot IDs are…
- Cannot filter timestamps using predicate:
- Cannot incrementally clean files when snapshots outside of…
- Cannot incrementally clean files when there are snapshots…
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 theView on GitHub (pinned to 86d9c8fc54)