apache/iceberg · error · IllegalArgumentException

Unexpected distribution mode:

Error message

Unexpected distribution mode: 

What it means

SparkWriteUtil.copyOnWriteDeleteUpdateDistribution builds distributions for copy-on-write DELETE/UPDATE writes per DistributionMode, with explicit branches for HASH and RANGE (and NONE handling above). An unexpected mode reaching the default branch throws IllegalArgumentException("Unexpected distribution mode: " + mode).

Source

Thrown at spark/v4.1/spark/src/main/java/org/apache/iceberg/spark/SparkWriteUtil.java:161

      case NONE:
        return Distributions.unspecified();

      case HASH:
        if (table.spec().isPartitioned()) {
          return Distributions.clustered(clustering(table));
        } else {
          return Distributions.clustered(FILE_CLUSTERING);
        }

      case RANGE:
        if (table.spec().isPartitioned() || table.sortOrder().isSorted()) {
          return Distributions.ordered(ordering(table));
        } else {
          return Distributions.ordered(EXISTING_ROW_ORDERING);
        }

      default:
        throw new IllegalArgumentException("Unexpected distribution mode: " + mode);
    }
  }

  /** Builds requirements for merge-on-read DELETE, UPDATE, MERGE operations. */
  public static SparkWriteRequirements positionDeltaRequirements(
      Table table,
      Command command,
      DistributionMode mode,
      boolean fanoutEnabled,
      long advisoryPartitionSize) {

    if (command == UPDATE || command == MERGE) {
      Distribution distribution = positionDeltaUpdateMergeDistribution(table, mode);
      SortOrder[] ordering = positionDeltaUpdateMergeOrdering(table, fanoutEnabled);
      return new SparkWriteRequirements(distribution, ordering, advisoryPartitionSize);
    } else {
      Distribution distribution = positionDeltaDeleteDistribution(table, mode);
      SortOrder[] ordering = fanoutEnabled ? EMPTY_ORDERING : POSITION_DELETE_ORDERING;

View on GitHub (pinned to 86d9c8fc54)

Solutions

  1. Configure distribution mode to one of none/hash/range for CoW delete/update writes
  2. Guard the call site by checking the resolved mode before invoking
  3. Update the switch to handle any newly introduced DistributionMode constants

Example fix

// before
Distribution d = SparkWriteUtil.copyOnWriteDeleteUpdateDistribution(table, mode, fanout); // throws
// after
if (mode == DistributionMode.HASH) {
  d = Distributions.clustered(SparkWriteUtil.clustering(table));
} else {
  d = SparkWriteUtil.copyOnWriteDeleteUpdateDistribution(table, mode, fanout);
}
Defensive patterns

Strategy: validation

Validate before calling

if (mode != DistributionMode.NONE && mode != DistributionMode.HASH && mode != DistributionMode.RANGE) {
  throw new IllegalArgumentException("CoW delete/update distribution requires NONE/HASH/RANGE, got: " + mode);
}

Type guard

boolean validForCoWDeleteUpdate(DistributionMode m) {
  return EnumSet.of(DistributionMode.NONE, DistributionMode.HASH, DistributionMode.RANGE).contains(m);
}

Try / catch

try {
  dist = SparkWriteUtil.copyOnWriteDeleteUpdateDistribution(table, mode, fanoutEnabled);
} catch (IllegalArgumentException e) {
  LOG.warn("Mode {} unsupported, ordering rows by existing order", mode, e);
  dist = Distributions.ordered(SparkWriteUtil.EXISTING_ROW_ORDERING);
}

Prevention

When it happens

Trigger: Calling copyOnWriteDeleteUpdateDistribution with a mode that is not NONE, HASH, or RANGE - e.g. a freshly added DistributionMode constant or a mode resolved from an invalid config value.

Common situations: write.distribution-mode / write.delete.distribution-mode configured to an unrecognized value; version skew introducing new enum constants not handled by this utility.

Related errors


AI-assisted analysis of apache/iceberg@86d9c8fc54 (2026-09-12). Data as JSON: /api/errors/43c38781f9f41b47. Report an issue: GitHub.