apache/beam · error · UnsupportedOperationException

Unknown scan type: {}

Error message

Unknown scan type: {}

What it means

ScanSource.split() switches over the scan configuration's scan type and throws UnsupportedOperationException for any value it does not explicitly handle (neither TABLE nor BATCH). This is a defensive default branch indicating the ScanConfig carried an unknown or newly-added Iceberg scan type the connector doesn't recognize.

Source

Thrown at sdks/java/io/iceberg/src/main/java/org/apache/beam/sdk/io/iceberg/ScanSource.java:101

      case TABLE:
        TableScan tableScan = getTableScan();
        if (desiredBundleSizeBytes > 0) {
          tableScan =
              tableScan.option(TableProperties.SPLIT_SIZE, Long.toString(desiredBundleSizeBytes));
        }

        try (CloseableIterable<CombinedScanTask> tasks = tableScan.planTasks()) {
          for (CombinedScanTask combinedScanTask : tasks) {
            splits.add(new ScanTaskSource(scanConfig, combinedScanTask));
          }
        } catch (IOException e) {
          throw new RuntimeException(e);
        }
        break;
      case BATCH:
        throw new UnsupportedOperationException("BATCH scan not supported");
      default:
        throw new UnsupportedOperationException("Unknown scan type: " + scanConfig.getScanType());
    }

    return splits;
  }

  @Override
  public long getEstimatedSizeBytes(PipelineOptions options) throws Exception {
    return wholeTableReadTask().sizeBytes();
  }

  @Override
  public void populateDisplayData(DisplayData.Builder builder) {
    super.populateDisplayData(builder);
  }

  @Override
  public Coder<Row> getOutputCoder() {
    return RowCoder.of(

View on GitHub (pinned to 12126d8942)

Solutions

  1. Log/inspect scanConfig.getScanType() to see the unexpected value.
  2. Fix the code that builds the ScanConfig so it sets a supported scan type (TABLE).
  3. Align the Beam IO iceberg connector version with the Iceberg library version in use.
  4. If a new scan type is legitimately needed, add a case for it in ScanSource.split().

Example fix

// before
ScanConfig cfg = ScanConfig.builder().build(); // scanType left unset
// after
ScanConfig cfg = ScanConfig.builder().setScanType(ScanType.TABLE).build();
Defensive patterns

Strategy: validation

Validate before calling

Object t = scanConfig.getScanType();
if (t != ScanType.TABLE && t != ScanType.INCREMENTAL /* supported types */) {
  throw new IllegalArgumentException("Unsupported scan type: " + t);
}

Try / catch

try {
  return source.split(desiredBundles, options);
} catch (UnsupportedOperationException e) {
  throw new IllegalStateException("Unknown scan type — check ScanConfig construction and library version alignment", e);
}

Prevention

When it happens

Trigger: scanConfig.getScanType() returns a value not covered by the switch cases in ScanSource.split(), e.g. a null, custom, or newer Iceberg ScanType enum value.

Common situations: Upgrading the Iceberg library introduced a new scan type the Beam connector version predates; a ScanConfig was built programmatically with a null/default scan type; a custom ScanType implementation was injected.

Understand the failure class

Background: Invalid enum value errors: "Unknown type", "Invalid scope", "must be one of" — when a string is not on the library's allowed list — this error's family across 23 libraries.

Related errors


AI-assisted analysis of apache/beam@12126d8942 (2026-09-13). Data as JSON: /api/errors/a494fae5c234102d. Report an issue: GitHub.