apache/iceberg · error · UnsupportedOperationException

Unsupported unit for timestamp

Error message

Unsupported unit for timestamp: %s

What it means

GenericParquetReaders.timestampReader selects timestamp readers by logical-type unit. MICROS and MILLIS have dedicated readers; any other unit (NANOS) throws UnsupportedOperationException because the generic readers don't convert nanosecond timestamps.

Solutions

  1. Rewrite the data with microsecond timestamps (Iceberg stores timestamps in micros).
  2. Cast/convert nanosecond columns before reading: read as INT64 and divide by 1000, or use a custom reader.
  3. Configure the upstream writer to emit TIMESTAMP_MICROS.

Example fix

// before: pyarrow writes ns timestamps
# table = pa.table({...}) ; pq.write_table(table, 'f.parquet')  # TIMESTAMP(NANOS)
// after
# table = table.set_column(i, 'ts', table['ts'].cast(pa.timestamp('us'))); pq.write_table(table, 'f.parquet')
Defensive patterns

Strategy: validation

Validate before calling

// Verify timestamp unit before reading
TimeUnit unit = col.getDateTimeUnit().getUnit();
if (unit == TimeUnit.NANOSECONDS) {
  throw new IllegalStateException("Rewrite to micros: unsupported timestamp unit NANOS");
}

Prevention

When it happens

Trigger: Reading a Parquet TIMESTAMP logical type with unit NANOS (adjusted-to-UTC or not) via GenericParquetReaders.

Common situations: Parquet files written by systems using nanosecond timestamps (e.g. pandas/pyarrow default, some legacy writers); mixing such files into Iceberg reads via the generic data readers.

Related errors


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

Appendix: source

Thrown at parquet/src/main/java/org/apache/iceberg/data/parquet/GenericParquetReaders.java:123

        "Invalid timestamp logical type: " + timestamp);

    LogicalTypeAnnotation.TimeUnit unit =
        ((LogicalTypeAnnotation.TimestampLogicalTypeAnnotation) timestamp).getUnit();
    switch (unit) {
      case NANOS:
        return isAdjustedToUTC
            ? new GenericParquetReaders.TimestamptzReader(desc, ChronoUnit.NANOS)
            : new GenericParquetReaders.TimestampReader(desc, ChronoUnit.NANOS);
      case MICROS:
        return isAdjustedToUTC
            ? new GenericParquetReaders.TimestamptzReader(desc, ChronoUnit.MICROS)
            : new GenericParquetReaders.TimestampReader(desc, ChronoUnit.MICROS);
      case MILLIS:
        return isAdjustedToUTC
            ? new GenericParquetReaders.TimestamptzMillisReader(desc)
            : new GenericParquetReaders.TimestampMillisReader(desc);
      default:
        throw new UnsupportedOperationException("Unsupported unit for timestamp: " + unit);
    }
  }

  @Override
  protected Object convertConstant(org.apache.iceberg.types.Type type, Object value) {
    return GenericDataUtil.internalToGeneric(type, value);
  }

  private static final OffsetDateTime EPOCH = Instant.ofEpochSecond(0).atOffset(ZoneOffset.UTC);
  private static final LocalDate EPOCH_DAY = EPOCH.toLocalDate();

  private static class DateReader extends ParquetValueReaders.PrimitiveReader<LocalDate> {
    DateReader(ColumnDescriptor desc) {
      super(desc);
    }

    @Override
    public LocalDate read(LocalDate reuse) {

View on GitHub (pinned to 86d9c8fc54)