apache/iceberg · error · UnsupportedOperationException

Void transform is not supported

Error message

Void transform is not supported

What it means

PartitionSpecVisitor's default alwaysNull() throws UnsupportedOperationException for partition fields using the Void transform. A Void transform results from partition-field evolution: a field is removed from the spec by replacing its transform with void, leaving the column all nulls. Dispatch in visit() matches VoidTransform and calls alwaysNull(); implementations that ignore void fields fail here unless they explicitly handle them.

Solutions

  1. Override alwaysNull(int fieldId, String sourceName, int sourceId) to emit the appropriate representation (e.g. a null-valued partition column or skip the field)
  2. Filter spec.fields() for transform instanceof VoidTransform before visiting and decide how to map them
  3. If the target cannot represent void partition fields, remap or drop them in the visitor implementation explicitly

Example fix

// before
visitor without alwaysNull override -> UnsupportedOperationException on evolved spec
// after
@Override
public String alwaysNull(int fieldId, String sourceName, int sourceId) {
  return null; // void partition field: all values are null
}
Defensive patterns

Strategy: validation

Validate before calling

boolean hasVoidTransform(PartitionSpec spec) {
  return spec.fields().stream().anyMatch(f -> f.transform() instanceof VoidTransform);
}
// indicates an evolved spec; decide before visiting how void fields map

Type guard

if (field.transform() instanceof VoidTransform) {
  // emit null representation or skip — do not rely on the throwing default
}

Try / catch

try {
  PartitionSpecVisitor.visit(spec, visitor);
} catch (UnsupportedOperationException e) {
  if (e.getMessage().contains("Void")) {
    LOG.warn("Spec has void partition fields (partition evolution); adjust visitor");
  }
  throw e;
}

Prevention

When it happens

Trigger: PartitionSpecVisitor.visit on a table whose partition spec contains a void transform — i.e. a partition field was removed via updatePartitionSpec/removeField and later the spec is visited by a visitor without an alwaysNull override.

Common situations: Tables whose partitioning was evolved (dropped/changed partition fields) visited by catalog translators that were written for specs with only live transforms; copying such a spec to a target catalog that cannot represent void fields.

Understand the failure class

Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.

Related errors


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

Appendix: source

Thrown at api/src/main/java/org/apache/iceberg/transforms/PartitionSpecVisitor.java:85

  default T day(int fieldId, String sourceName, int sourceId) {
    return day(sourceName, sourceId);
  }

  default T day(String sourceName, int sourceId) {
    throw new UnsupportedOperationException("Day transform is not supported");
  }

  default T hour(int fieldId, String sourceName, int sourceId) {
    return hour(sourceName, sourceId);
  }

  default T hour(String sourceName, int sourceId) {
    throw new UnsupportedOperationException("Hour transform is not supported");
  }

  default T alwaysNull(int fieldId, String sourceName, int sourceId) {
    throw new UnsupportedOperationException("Void transform is not supported");
  }

  default T unknown(int fieldId, String sourceName, int sourceId, String transform) {
    throw new UnsupportedOperationException(
        String.format("Unknown transform %s is not supported", transform));
  }

  /**
   * Visit the fields of a {@link PartitionSpec}.
   *
   * @param spec a partition spec to visit
   * @param visitor a partition spec visitor
   * @param <R> return type of the visitor
   * @return a list of the result produced by visiting each partition field
   */
  static <R> List<R> visit(PartitionSpec spec, PartitionSpecVisitor<R> visitor) {
    List<R> results = Lists.newArrayListWithExpectedSize(spec.fields().size());

View on GitHub (pinned to 86d9c8fc54)