apache/iceberg · error · UnsupportedOperationException

Hour transform is not supported

Error message

Hour transform is not supported

What it means

PartitionSpecVisitor's default hour() methods throw UnsupportedOperationException when the visitor does not implement the hour temporal transform. Dispatch in PartitionSpecVisitor.visit matches Timestamps.MICROS_TO_HOUR/NANOS_TO_HOUR or Hours and calls hour(); the throwing default indicates the concrete visitor's transform coverage is incomplete. This intentional failure prevents a silently wrong partition-field mapping.

Source

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

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

  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

View on GitHub (pinned to 86d9c8fc54)

Solutions

  1. Override hour(int fieldId, String sourceName, int sourceId) in your visitor to handle the hour transform
  2. Validate the spec's partitionType() up front to detect hour transforms and route to a supported path
  3. If hourly partitioning is unsupported downstream, override hour() to produce an explicit unsupported error in your own terms

Example fix

// before
visitor without hour override -> UnsupportedOperationException
// after
@Override
public String hour(int fieldId, String sourceName, int sourceId) {
  return "hours(" + sourceName + ")";
}
Defensive patterns

Strategy: validation

Validate before calling

boolean hasHourTransform(PartitionSpec spec) {
  return spec.fields().stream().anyMatch(f -> f.transform() instanceof Hours
      || f.transform() == Timestamps.MICROS_TO_HOUR || f.transform() == Timestamps.NANOS_TO_HOUR);
}
// reject early or add hour() support before visiting

Type guard

if (field.transform() instanceof Hours) {
  throw new IllegalStateException("Visitor does not support hour transform: " + field);
}

Try / catch

try {
  PartitionSpecVisitor.visit(spec, visitor);
} catch (UnsupportedOperationException e) {
  throw new IllegalStateException("Hour-partitioned table not supported by this visitor", e);
}

Prevention

When it happens

Trigger: PartitionSpecVisitor.visit on a table partitioned with hour(ts_col) where the visitor implementation lacks hour(int, String, int) or hour(String, int) overrides.

Common situations: Streaming/high-frequency ingestion tables are often partitioned by hour; custom visitor-based translators written for batch tables (identity/day only) blow up when pointed at such tables. Also occurs when copying specs between catalogs that don't support hourly partitioning.

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/d2f486181380f3ab. Report an issue: GitHub.