apache/iceberg · error · UnsupportedOperationException

Cannot scan table using scan snapshot id %s: configured for

Error message

Cannot scan table using scan snapshot id %s: configured for incremental data in snapshots (%s, %s]

What it means

useSnapshot pins a scan to one snapshot, which conflicts with an incremental scan's (fromSnapshotId, toSnapshotId) range. IncrementalDataTableScan rejects it with UnsupportedOperationException, echoing the configured range, because an incremental scan must compare two snapshots, not read one.

Source

Thrown at core/src/main/java/org/apache/iceberg/IncrementalDataTableScan.java:57

  @Override
  public TableScan asOfTime(long timestampMillis) {
    throw new UnsupportedOperationException(
        String.format(
            "Cannot scan table as of time %s: configured for incremental data in snapshots (%s, %s]",
            timestampMillis, context().fromSnapshotId(), context().toSnapshotId()));
  }

  @Override
  public TableScan useRef(String ref) {
    throw new UnsupportedOperationException(
        String.format(
            "Cannot scan table using ref %s: configured for incremental data in snapshots (%s, %s]",
            ref, context().fromSnapshotId(), context().toSnapshotId()));
  }

  @Override
  public TableScan useSnapshot(long scanSnapshotId) {
    throw new UnsupportedOperationException(
        String.format(
            "Cannot scan table using scan snapshot id %s: configured for incremental data in snapshots (%s, %s]",
            scanSnapshotId, context().fromSnapshotId(), context().toSnapshotId()));
  }

  @Override
  public TableScan appendsBetween(long fromSnapshotId, long toSnapshotId) {
    validateSnapshotIdsRefinement(fromSnapshotId, toSnapshotId);
    return new IncrementalDataTableScan(
        table(),
        schema(),
        context().fromSnapshotIdExclusive(fromSnapshotId).toSnapshotId(toSnapshotId));
  }

  @Override
  public TableScan appendsAfter(long newFromSnapshotId) {
    final Snapshot currentSnapshot = table().currentSnapshot();
    Preconditions.checkState(

View on GitHub (pinned to 86d9c8fc54)

Solutions

  1. Drop the useSnapshot call and configure fromSnapshot(long)/toSnapshot(long) for the incremental range.
  2. If a single-snapshot read is wanted, use table.scan().useSnapshot(id) instead of an incremental scan.
  3. Guard ref/snapshot pinning behind an instanceof check for incremental scans.

Example fix

// before
TableScan scan = table.incrementalScan(startId).useSnapshot(targetId);
// after
TableScan scan = table.incrementalScan(startId, targetId);
Defensive patterns

Strategy: type-guard

Validate before calling

if (scan instanceof org.apache.iceberg.IncrementalDataTableScan) {
  // pass the id via toSnapshot, not useSnapshot
}

Type guard

boolean supportsSingleSnapshotScan(TableScan scan) {
  return !(scan instanceof org.apache.iceberg.IncrementalDataTableScan);
}

Try / catch

try {
  scan.useSnapshot(id);
} catch (UnsupportedOperationException e) {
  scan = table.incrementalScan(fromId, id);
}

Prevention

When it happens

Trigger: Calling table.incrementalScan(...).useSnapshot(snapshotId) on an incremental scan result.

Common situations: Reuse of scan builders shared between normal and incremental scans; reading engines that pass 'snapshot-id' as a generic scan option to all scan types.

Understand the failure class

Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.

Related errors


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