apache/iceberg · error · UnsupportedOperationException

Using a reference is not supported

Error message

Using a reference is not supported

What it means

The default TableScan.useRef(String) throws UnsupportedOperationException because a TableScan implementation may not support snapshot references (branches/tags). Implementations such as DataTableScan override it; other TableScan implementations (metadata-table scans, custom scans) keep the throwing default.

Solutions

  1. Obtain the TableScan from table.newScan() on a real data table (DataTableScan supports useRef).
  2. Instead of useRef, select the snapshot explicitly via useSnapshotId(snapshotId) resolved through table.snapshot(ref) or table.refs().get(ref).
  3. Catch UnsupportedOperationException and fall back to snapshot-ID-based refinement.
  4. Override useRef in custom TableScan implementations.

Example fix

// before
TableScan scan = table.newScan().useRef("audit-branch");

// after
Snapshot snap = table.snapshot("audit-branch");
TableScan scan = (snap != null)
    ? table.newScan().useSnapshotId(snap.snapshotId())
    : table.newScan();
Defensive patterns

Strategy: validation

Validate before calling

Snapshot ref = table.snapshot("audit-branch");
if (ref == null) {
  throw new IllegalArgumentException("Reference not found: audit-branch");
}
TableScan scan = table.newScan().useSnapshotId(ref.snapshotId());

Type guard

TableScan safeUseRef(Table t, String ref) {
  Snapshot s = t.snapshot(ref);
  return (s != null) ? t.newScan().useSnapshotId(s.snapshotId()) : t.newScan();
}

Try / catch

try {
  scan = table.newScan().useRef(ref);
} catch (UnsupportedOperationException e) {
  Snapshot s = table.snapshot(ref);
  scan = (s != null) ? table.newScan().useSnapshotId(s.snapshotId()) : table.newScan();
}

Prevention

When it happens

Trigger: Calling scan.useRef("branch-name") (directly, or via helpers like planTasks/canDeleteUsingMetadata/dataFiles that refine scans with a reference) on a TableScan implementation that doesn't override useRef.

Common situations: Running Spark/Merge-on-read delete planning against metadata tables or custom scans; applying branch/tag-based reads to scan objects obtained from non-standard scan implementations; copy-on-write utilities selecting a snapshot by reference name.

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/5f0784772ad808a2. Report an issue: GitHub.

Appendix: source

Thrown at api/src/main/java/org/apache/iceberg/TableScan.java:49

   * Create a new {@link TableScan} from this scan's configuration that will use the given snapshot
   * by ID.
   *
   * @param snapshotId a snapshot ID
   * @return a new scan based on this with the given snapshot ID
   * @throws IllegalArgumentException if the snapshot cannot be found
   */
  TableScan useSnapshot(long snapshotId);

  /**
   * Create a new {@link TableScan} from this scan's configuration that will use the given
   * reference.
   *
   * @param ref reference
   * @return a new scan based on the given reference.
   * @throws IllegalArgumentException if a reference with the given name could not be found
   */
  default TableScan useRef(String ref) {
    throw new UnsupportedOperationException("Using a reference is not supported");
  }

  /**
   * Create a new {@link TableScan} from this scan's configuration that will use the most recent
   * snapshot as of the given time in milliseconds on the branch in the scan or main if no branch is
   * set.
   *
   * @param timestampMillis a timestamp in milliseconds.
   * @return a new scan based on this with the current snapshot at the given time
   * @throws IllegalArgumentException if the snapshot cannot be found or time travel is attempted on
   *     a tag
   */
  TableScan asOfTime(long timestampMillis);

  /**
   * Create a new {@link TableScan} to read appended data from {@code fromSnapshotId} exclusive to
   * {@code toSnapshotId} inclusive.
   *

View on GitHub (pinned to 86d9c8fc54)