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
- Fix the field's Iceberg type: use Types.TimestampType (withZone) for zoned values and TimestampType without zone for LocalDateTime-backed values.
- Ensure the value reader emits Long (epoch nanos) or LocalDateTime for timestamp_ns fields.
- Convert the value upstream (e.g. to LocalDateTime or epoch nanos Long) before projection.
- 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
- Map zoned values to TimestampType.withZone and local values to withoutZone
- Ensure readers emit Long (epoch nanos) or LocalDateTime for TIMESTAMP(9) fields
- Cover timestamp precision paths in reader unit tests
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
- Unknown type for long field. Type name: ${className}
- Unknown type for int field. Type name: ${className}
- Unexpected object type for TIMESTAMP logical type. Received:
- Unknown type for int field. Type name: ${integer.getClass().
- Unknown type for long field. Type name: ${longVal.getClass()
AI-assisted analysis of apache/iceberg@86d9c8fc54 (2026-09-12).
Data as JSON: /api/errors/ae18d96c3c4ad82f.
Report an issue: GitHub.