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
- Remove sortBy(...) and run the rewrite with the implementation's default clustering
- Use Spark's RewriteManifests implementation, which supports sortBy
- Check the concrete class for a sortBy override before configuring partition clustering
- 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
- Only use sortBy on implementations that support partition-clustered manifests (Spark)
- Read the UnsupportedOperationException message: it names the concrete class lacking support
- Keep manifest compaction logic per-engine
- Add a capability check before configuring manifest clustering
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
- Backup table name cannot be specified
- Setting executor service is not supported
- Ignoring missing files is not supported
- Can't retrieve values from an empty struct
- Can't modify an empty struct
AI-assisted analysis of apache/iceberg@86d9c8fc54 (2026-09-12).
Data as JSON: /api/errors/f2e1fcaa4b616178.
Report an issue: GitHub.