apache/iceberg · error

Unsupported time unit: + timestampUnit

Error message

Unsupported time unit: + timestampUnit

What it means

Thrown by the bound Timestamps transform's apply() when the timestamp precision unit itself (the outer switch) is neither MICROS nor NANOS. Iceberg only defines two timestamp precisions — microseconds and nanoseconds — so a Timestamps transform built with any other ChronoUnit as the unit is fundamentally unusable.

Source

Thrown at api/src/main/java/org/apache/iceberg/transforms/Timestamps.java:94

              return DateTimeUtil.microsToHours(timestamp);
            default:
              throw new UnsupportedOperationException("Unsupported time unit: " + granularity);
          }
        case NANOS:
          switch (granularity) {
            case YEARS:
              return DateTimeUtil.nanosToYears(timestamp);
            case MONTHS:
              return DateTimeUtil.nanosToMonths(timestamp);
            case DAYS:
              return DateTimeUtil.nanosToDays(timestamp);
            case HOURS:
              return DateTimeUtil.nanosToHours(timestamp);
            default:
              throw new UnsupportedOperationException("Unsupported time unit: " + granularity);
          }
        default:
          throw new UnsupportedOperationException("Unsupported time unit: " + timestampUnit);
      }
    }
  }

  private final ChronoUnit granularity;
  private final String name;
  private final Apply apply;

  Timestamps(ChronoUnit granularity, String name, TimestampUnit timestampUnit) {
    this.name = name;
    this.granularity = granularity;
    this.apply = new Apply(granularity, timestampUnit);
  }

  /**
   * Transforms a value to its corresponding partition value.
   *
   * @param timestamp a source value

View on GitHub (pinned to 86d9c8fc54)

Solutions

  1. Construct the transform only with ChronoUnit.MICROS or ChronoUnit.NANOS as the timestamp unit
  2. Use Transforms.year/month/day/hour factory methods, which always produce a valid precision/granularity pair
  3. Validate the precision field when deserializing transform specs and reject unknown values early

Example fix

// before
new Timestamps(ChronoUnit.SECONDS, ChronoUnit.DAYS);
// after
new Timestamps(ChronoUnit.MICROS, ChronoUnit.DAYS);
Defensive patterns

Strategy: validation

Validate before calling

if (unit != ChronoUnit.MICROS && unit != ChronoUnit.NANOS) {
  throw new IllegalArgumentException("Timestamp unit must be MICROS or NANOS, got: " + unit);
}

Try / catch

try { Object v = tsTransform.bind(type).apply(value); } catch (UnsupportedOperationException e) { /* invalid precision: rebuild transform via Transforms.day(...) */ }

Prevention

When it happens

Trigger: Calling apply() on a bound Timestamps transform whose timestampUnit is ChronoUnit.SECOND, MINUTE, or any unit other than MICROS/NANOS — e.g. from a hand-constructed or deserialized transform with a bogus precision.

Common situations: Custom code constructing Timestamps directly instead of via Transforms factories; parsing a partition spec where the timestamp precision field was corrupted or hand-edited.

Related errors


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