apache/iceberg · error · UnsupportedOperationException

this.getClass().getName() + " doesn't implement sortBy(List<

Error message

this.getClass().getName() + " doesn't implement sortBy(List<String>)"

What it means

RewriteManifests.sortBy(List<String>) asks the rewrite-manifests action to cluster manifests by the given partition fields. The interface default throws UnsupportedOperationException with the concrete class name, because some implementations (e.g. Flink's) do not support custom manifest clustering.

Source

Thrown at api/src/main/java/org/apache/iceberg/actions/RewriteManifests.java:69

   * <p>Supply an optional set of partition field names to sort the rewritten manifests by. Choosing
   * a frequently queried partition field can reduce planning time by skipping unnecessary
   * manifests.
   *
   * <p>For example, given a table PARTITIONED BY (a, b, c, d), one may wish to rewrite and sort
   * manifests by ('d', 'b') only, based on known query patterns. Rewriting Manifests in this way
   * will yield a manifest_list whose manifest_files point to data files containing common 'd' then
   * 'b' partition values.
   *
   * <p>If not set, manifests will be rewritten in the order of the transforms in the table's
   * partition spec.
   *
   * @param partitionFields Exact transformed column names used for partitioning; not the raw column
   *     names that partitions are derived from. E.G. supply 'data_bucket' and not 'data' for a
   *     bucket(N, data) partition * definition
   * @return this for method chaining
   */
  default RewriteManifests sortBy(List<String> partitionFields) {
    throw new UnsupportedOperationException(
        this.getClass().getName() + " doesn't implement sortBy(List<String>)");
  }

  /**
   * Passes a location where the staged manifests should be written.
   *
   * <p>If not set, defaults to the table's metadata location.
   *
   * @param stagingLocation a staging location
   * @return this for method chaining
   */
  RewriteManifests stagingLocation(String stagingLocation);

  /** The action result that contains a summary of the execution. */
  interface Result {
    /** Returns rewritten manifests. */
    Iterable<ManifestFile> rewrittenManifests();

View on GitHub (pinned to 86d9c8fc54)

Solutions

  1. Remove sortBy(...) and run the rewrite with the implementation's default clustering
  2. Use Spark's RewriteManifests implementation, which supports sortBy
  3. Check the concrete class for a sortBy override before configuring partition clustering
  4. Implement sortBy in a custom action binding if partition-clustered manifests are required

Example fix

// before
RewriteManifests.Result r = actions.rewriteManifests(table)
    .sortBy(List.of("data_bucket"))
    .execute();
// after
RewriteManifests.Result r = actions.rewriteManifests(table)
    .execute(); // default clustering
Defensive patterns

Strategy: try-catch

Try / catch

try {
  rewriteManifests.sortBy(partitionFields);
} catch (UnsupportedOperationException e) {
  // run with default manifest clustering
}

Prevention

When it happens

Trigger: Calling rewriteManifests(table).sortBy(partitionFields) on an implementation keeping the default stub; the message names the concrete class, e.g. "...RewriteManifestsFlinkImpl doesn't implement sortBy(List<String>)".

Common situations: Users porting Spark manifest-compaction jobs that group manifests by partition to Flink or custom engines where only default (writer-based) clustering exists.

Related errors


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