apache/iceberg · error · UnsupportedOperationException

Cannot incrementally scan table of type %s

Error message

Cannot incrementally scan table of type %s

What it means

appendsBetween is only implemented by the incremental-scan metadata table (MetadataTableType.ENTRIES-based IncrementalAppendScan). BaseMetadataTableScan is the shared base for all metadata table scans, and most types (files, history, partitions, refs, etc.) cannot answer incremental append queries, so they throw UnsupportedOperationException.

Source

Thrown at core/src/main/java/org/apache/iceberg/BaseMetadataTableScan.java:50

  protected BaseMetadataTableScan(
      Table table, Schema schema, MetadataTableType tableType, TableScanContext context) {
    super(table, schema, context);
    this.tableType = tableType;
  }

  /**
   * Type of scan being performed, such as {@link MetadataTableType#ALL_DATA_FILES} when scanning a
   * table's {@link org.apache.iceberg.AllDataFilesTable}.
   *
   * <p>Used for logging and error messages.
   */
  protected MetadataTableType tableType() {
    return tableType;
  }

  @Override
  public TableScan appendsBetween(long fromSnapshotId, long toSnapshotId) {
    throw new UnsupportedOperationException(
        String.format("Cannot incrementally scan table of type %s", tableType()));
  }

  @Override
  public TableScan appendsAfter(long fromSnapshotId) {
    throw new UnsupportedOperationException(
        String.format("Cannot incrementally scan table of type %s", tableType()));
  }

  @Override
  public long targetSplitSize() {
    long tableValue =
        ((BaseTable) table())
            .operations()
            .current()
            .propertyAsLong(
                TableProperties.METADATA_SPLIT_SIZE, TableProperties.METADATA_SPLIT_SIZE_DEFAULT);
    return PropertyUtil.propertyAsLong(options(), TableProperties.SPLIT_SIZE, tableValue);

View on GitHub (pinned to 86d9c8fc54)

Solutions

  1. Only call appendsBetween on the incremental append metadata table (TableIdentifier with name 'append-scan' style usage) or the data table's createIncrementalScan
  2. Guard with instanceof TableScanIncrementalAppend/feature checks before invoking
  3. Compute appends manually from history/entries metadata tables if the type lacks support

Example fix

// before
MetadataTableType type = ...; // e.g. FILES
Table meta = MetadataTableUtils.createMetadataTableInstance(ops, ..., type);
meta.newScan().appendsBetween(from, to); // throws
// after
Table meta = MetadataTableUtils.createMetadataTableInstance(ops, ..., MetadataTableType.INCREMENTAL_APPEND_SCAN);
meta.newScan().appendsBetween(from, to);
Defensive patterns

Strategy: type-guard

Validate before calling

boolean supportsIncremental = table instanceof IncrementalAppendScan || table.name().endsWith("incremental-append-scan");

Type guard

if (scan instanceof IncrementalAppendScan) { ((IncrementalAppendScan) scan).appendsBetween(from, to); } else { /* unsupported */ }

Try / catch

try { return scan.appendsBetween(from, to); } catch (UnsupportedOperationException e) { return manualIncrementalFromHistory(table, from, to); }

Prevention

When it happens

Trigger: Calling ((IncrementalScan) MetadataTableUtils.createMetadataTableInstance(...)).appendsBetween(...) on a metadata table that is not the incremental-append table, e.g. loading table.references() then calling appendsBetween.

Common situations: Generic code that takes a Table and unconditionally calls appendsBetween assuming any table (including metadata tables) supports it.

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