apache/iceberg · error · UnsupportedOperationException

Unsupported delete granularity: ${granularity}

Error message

Unsupported delete granularity: ${granularity}

What it means

SortingPositionOnlyDeleteWriter.close() dispatches on the configured DeleteGranularity (FILE, PARTITION, etc.); any other value falls through to default and throws UnsupportedOperationException. This means the writer was configured with a granularity it cannot produce.

Source

Thrown at core/src/main/java/org/apache/iceberg/deletes/SortingPositionOnlyDeleteWriter.java:111

  }

  @Override
  public DeleteWriteResult result() {
    return result;
  }

  @Override
  public void close() throws IOException {
    if (result == null) {
      switch (granularity) {
        case FILE:
          this.result = writeFileDeletes();
          return;
        case PARTITION:
          this.result = writePartitionDeletes();
          return;
        default:
          throw new UnsupportedOperationException("Unsupported delete granularity: " + granularity);
      }
    }
  }

  // write deletes for all data files together
  private DeleteWriteResult writePartitionDeletes() throws IOException {
    return writeDeletes(positionsByPath.keySet());
  }

  // write deletes for different data files into distinct delete files
  private DeleteWriteResult writeFileDeletes() throws IOException {
    List<DeleteFile> deleteFiles = Lists.newArrayList();
    CharSequenceSet referencedDataFiles = CharSequenceSet.empty();
    List<DeleteFile> rewrittenDeleteFiles = Lists.newArrayList();

    for (CharSequence path : positionsByPath.keySet()) {
      DeleteWriteResult writeResult = writeDeletes(ImmutableList.of(path));
      deleteFiles.addAll(writeResult.deleteFiles());

View on GitHub (pinned to 86d9c8fc54)

Solutions

  1. Configure the writer with DeleteGranularity.FILE or DeleteGranularity.PARTITION
  2. If a new granularity value was introduced, upgrade Iceberg so the writer supports it, or handle it in writePartitionDeletes-style methods
  3. Add a case for the new granularity in close() if extending the writer yourself

Example fix

// before
DeleteGranularity granularity = DeleteGranularity.valueOf(cfg); // e.g. NEW_VALUE
// after
if (granularity != DeleteGranularity.FILE && granularity != DeleteGranularity.PARTITION) {
  throw new IllegalArgumentException("Sorting writer requires FILE or PARTITION, got: " + granularity);
}
Defensive patterns

Strategy: validation

Validate before calling

Preconditions.checkArgument(granularity == DeleteGranularity.FILE || granularity == DeleteGranularity.PARTITION, "Unsupported granularity: %s", granularity);

Type guard

boolean writerSupports(DeleteGranularity g) { return g == DeleteGranularity.FILE || g == DeleteGranularity.PARTITION; }

Try / catch

try { writer.close(); } catch (UnsupportedOperationException e) { throw new IllegalArgumentException("Check writer DeleteGranularity config", e); }

Prevention

When it happens

Trigger: Constructing a SortingPositionOnlyDeleteWriter with a DeleteGranularity other than FILE or PARTITION (e.g. a newly added enum value the writer does not handle) and then calling close().

Common situations: Enum evolution: a new DeleteGranularity value added to the API but not yet supported by the sorting writer; custom writer configs passing an invalid granularity value.

Related errors


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