apache/iceberg · error · UnsupportedOperationException

Cannot scan table using ref %s: configured for incremental d

Error message

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

What it means

An incremental scan is pinned to a snapshot range (fromSnapshotId, toSnapshotId); switching it to a named ref/branch would replace that range with a single snapshot, which the scan does not support. useRef therefore throws UnsupportedOperationException unconditionally, reporting the configured range.

Source

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

import org.apache.iceberg.util.SnapshotUtil;

class IncrementalDataTableScan extends DataTableScan {
  IncrementalDataTableScan(Table table, Schema schema, TableScanContext context) {
    super(table, schema, context.useSnapshotId(null));
    validateSnapshotIds(table, context.fromSnapshotId(), context.toSnapshotId());
  }

  @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(),

View on GitHub (pinned to 86d9c8fc54)

Solutions

  1. Remove the useRef call; select the snapshot range with fromSnapshot(long) and toSnapshot(long) instead.
  2. To scan a branch incrementally, resolve its current snapshot ID (SnapshotUtil.currentSnapshotId or table.snapshot(ref).snapshotId()) and pass it as toSnapshotId.
  3. Guard with (scan instanceof IncrementalDataTableScan) before applying ref-based configuration.

Example fix

// before
TableScan scan = table.incrementalScan(startId).useRef("audit");
// after
long endId = table.snapshot("audit").snapshotId();
TableScan scan = table.incrementalScan(startId, endId);
Defensive patterns

Strategy: type-guard

Validate before calling

if (scan instanceof org.apache.iceberg.IncrementalDataTableScan) {
  // use fromSnapshot/toSnapshot instead of useRef
}

Type guard

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

Try / catch

try {
  scan.useRef(ref);
} catch (UnsupportedOperationException e) {
  long endId = table.snapshot(ref).snapshotId();
  scan = table.incrementalScan(fromId, endId);
}

Prevention

When it happens

Trigger: Calling table.incrementalScan(...).useRef("branch-name") on an incremental scan result.

Common situations: Generic scan-option plumbing that always sets a ref (e.g. 'snapshot-id'/'branch' options applied uniformly); users migrating from branch-scoped snapshot scans to incremental scans who keep the useRef call.

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/3bd227de7b908319. Report an issue: GitHub.