apache/iceberg · error · UnsupportedOperationException

Unsupported split change: {splitsChange.getClass()}

Error message

Unsupported split change: {splitsChange.getClass()}

What it means

IcebergSourceSplitReader.handleSplitsChanges only supports SplitsAddition; any other SplitsChange type (e.g. SplitsRemoval) is rejected with UnsupportedOperationException. The batch reader model never shrinks its assigned split set, so removal changes indicate an unsupported source-event flow.

Source

Thrown at flink/v2.1/flink/src/main/java/org/apache/iceberg/flink/source/reader/IcebergSourceSplitReader.java:109

    }

    if (currentReader.hasNext()) {
      // Because Iterator#next() doesn't support checked exception,
      // we need to wrap and unwrap the checked IOException with UncheckedIOException
      try {
        return currentReader.next();
      } catch (UncheckedIOException e) {
        throw e.getCause();
      }
    } else {
      return finishSplit();
    }
  }

  @Override
  public void handleSplitsChanges(SplitsChange<IcebergSourceSplit> splitsChange) {
    if (!(splitsChange instanceof SplitsAddition)) {
      throw new UnsupportedOperationException(
          String.format("Unsupported split change: %s", splitsChange.getClass()));
    }

    if (splitComparator != null) {
      List<IcebergSourceSplit> newSplits = Lists.newArrayList(splitsChange.splits());
      newSplits.sort(splitComparator);
      LOG.info("Add {} splits to reader: {}", newSplits.size(), newSplits);
      splits.addAll(newSplits);
    } else {
      LOG.info("Add {} splits to reader", splitsChange.splits().size());
      splits.addAll(splitsChange.splits());
    }
    metrics.incrementAssignedSplits(splitsChange.splits().size());
    metrics.incrementAssignedBytes(calculateBytes(splitsChange));
  }

  @Override
  public void wakeUp() {

View on GitHub (pinned to 86d9c8fc54)

Solutions

  1. Ensure the enumerator used with IcebergSource only emits SplitsAddition (use the provided IcebergEnumerator, not a custom one emitting removals).
  2. Check that you are not combining the legacy FlinkInputFormat source with the new Source API split changes.
  3. If using HybridSource or hand-off, verify the hand-off contract produces additions only, or upgrade to a connector version supporting the change type.
  4. Capture splitsChange.getClass() from the message to identify which framework component emitted the unsupported change.

Example fix

// before: custom enumerator
new SplitEnumerator() { ... context.assignSplits(removal); ... }
// after: use Iceberg's enumerator
new ContinuousIcebergEnumerator(context, splitPlanner, scanContext);
Defensive patterns

Strategy: type-guard

Validate before calling

// guard before delegating split changes to the reader
if (splitsChange != null && !(splitsChange instanceof SplitsAddition)) {
  LOG.warn("Ignoring unsupported split change: {}", splitsChange.getClass());
  return;
}

Type guard

boolean isAddition(SplitsChange<IcebergSourceSplit> c) {
  return c instanceof SplitsAddition;
}

Prevention

When it happens

Trigger: The SourceReaderContext/reader pipeline delivers a SplitsChange that is not a SplitsAddition to handleSplitsChanges — typically a removal generated by a different source implementation or by hybrid source hand-off logic.

Common situations: Mixing the v1 and v2 Flink source implementations; using IcebergSource inside frameworks (e.g. HybridSource, custom enumerator wrappers) that emit removals; upgrading Flink where the framework emits different split-change events.

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