apache/iceberg · error · IllegalStateException

Unknown type for timestamp_ns: ${class}

Error message

Unknown type for timestamp_ns: ${class}

What it means

StructRowData.getTimestamp(pos) converts a timestamp_ns field into Flink TimestampData. Supported internal values are LocalDateTime and Long (epoch nanos); any other class throws IllegalStateException 'Unknown type for timestamp_ns'. The error indicates the internal value representation does not match the declared nanosecond timestamp field.

Source

Thrown at flink/v1.20/flink/src/main/java/org/apache/iceberg/flink/data/StructRowData.java:204

  @Override
  public TimestampData getTimestamp(int pos, int precision) {
    if (precision > 6) {
      Object timeVal = struct.get(pos, Object.class);
      if (timeVal instanceof OffsetDateTime) {
        OffsetDateTime odt = (OffsetDateTime) timeVal;
        return TimestampData.fromEpochMillis(
            odt.toInstant().toEpochMilli(), odt.getNano() % 1_000_000);
      } else if (timeVal instanceof LocalDateTime) {
        LocalDateTime ldt = (LocalDateTime) timeVal;
        return TimestampData.fromEpochMillis(
            ldt.toInstant(ZoneOffset.UTC).toEpochMilli(), ldt.getNano() % 1_000_000);
      } else if (timeVal instanceof Long) {
        long timeLong = (Long) timeVal;
        return TimestampData.fromEpochMillis(
            Math.floorDiv(timeLong, 1_000_000L), (int) Math.floorMod(timeLong, 1_000_000L));
      } else {
        throw new IllegalStateException("Unknown type for timestamp_ns: " + timeVal.getClass());
      }
    }
    long timeLong = getLong(pos);
    return TimestampData.fromEpochMillis(
        Math.floorDiv(timeLong, 1000L), (int) Math.floorMod(timeLong, 1000L) * 1000);
  }

  @Override
  public <T> RawValueData<T> getRawValue(int pos) {
    throw new UnsupportedOperationException("Not supported yet.");
  }

  @Override
  public byte[] getBinary(int pos) {
    return isNullAt(pos) ? null : getBinaryInternal(pos);
  }

  private byte[] getBinaryInternal(int pos) {

View on GitHub (pinned to 86d9c8fc54)

Solutions

  1. Fix the field's Iceberg type: use Types.TimestampType (withZone) for zoned values and TimestampType without zone for LocalDateTime-backed values.
  2. Ensure the value reader emits Long (epoch nanos) or LocalDateTime for timestamp_ns fields.
  3. Convert the value upstream (e.g. to LocalDateTime or epoch nanos Long) before projection.
  4. Match writer/reader Iceberg versions to keep internal timestamp representations consistent.

Example fix

// before: value stored as OffsetDateTime, field projected as TIMESTAMP(9) (local)
schema.add("ts", Types.TimestampType.withoutZone()); // reader emits OffsetDateTime -> throws
// after: read with withZone() type, or convert to LocalDateTime before projection
schema.add("ts", Types.TimestampType.withZone());
Defensive patterns

Strategy: type-guard

Validate before calling

if (!(v instanceof LocalDateTime || v instanceof Long)) {
  throw new IllegalArgumentException("value not timestamp_ns-compatible: " + v.getClass());
}

Type guard

boolean isTimestampNsCompatible(Object v) {
  return v instanceof LocalDateTime || v instanceof Long;
}

Try / catch

try {
  TimestampData ts = structRow.getTimestamp(pos, 9);
} catch (IllegalStateException e) {
  if (e.getMessage().startsWith("Unknown type for timestamp_ns")) {
    // convert to LocalDateTime/epoch-nanos or correct the withZone/withoutZone mapping
  }
}

Prevention

When it happens

Trigger: A field declared as TIMESTAMP(9)/timestamp_ns whose value is, e.g., OffsetDateTime, TimestampData, or String - typically because the reader produced a micros-style or zoned representation while the projected type expects nanos as Long or LocalDateTime.

Common situations: Schema mapping confusion between timestamp (micros) and timestamptz (zoned) types; custom readers emitting OffsetDateTime for a local-timestamp field; data written by other engines with different timestamp classes in Iceberg's internal struct.

Understand the failure class

Background: Type mismatch errors: IllegalArgumentException, TypeError and type guards across 150 open-source libraries — this error's family across 150 libraries.

Related errors


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