{"record":{"id":"c2af360564416f5a","repo":"apache/iceberg","slug":"unknown-type-for-timestamp-ns-timeval-getclas","errorCode":null,"errorMessage":"Unknown type for timestamp_ns: \" + timeVal.getClass()","messagePattern":"Unknown type for timestamp_ns: \" \\+ timeVal\\.getClass\\(\\)","errorType":"exception","errorClass":"IllegalStateException","httpStatus":null,"severity":"error","filePath":"flink/v2.2/flink/src/main/java/org/apache/iceberg/flink/data/StructRowData.java","lineNumber":205,"sourceCode":"\n  @Override\n  public TimestampData getTimestamp(int pos, int precision) {\n    if (precision > 6) {\n      Object timeVal = struct.get(pos, Object.class);\n      if (timeVal instanceof OffsetDateTime) {\n        OffsetDateTime odt = (OffsetDateTime) timeVal;\n        return TimestampData.fromEpochMillis(\n            odt.toInstant().toEpochMilli(), odt.getNano() % 1_000_000);\n      } else if (timeVal instanceof LocalDateTime) {\n        LocalDateTime ldt = (LocalDateTime) timeVal;\n        return TimestampData.fromEpochMillis(\n            ldt.toInstant(ZoneOffset.UTC).toEpochMilli(), ldt.getNano() % 1_000_000);\n      } else if (timeVal instanceof Long) {\n        long timeLong = (Long) timeVal;\n        return TimestampData.fromEpochMillis(\n            Math.floorDiv(timeLong, 1_000_000L), (int) Math.floorMod(timeLong, 1_000_000L));\n      } else {\n        throw new IllegalStateException(\"Unknown type for timestamp_ns: \" + timeVal.getClass());\n      }\n    }\n    long timeLong = getLong(pos);\n    return TimestampData.fromEpochMillis(\n        Math.floorDiv(timeLong, 1000L), (int) Math.floorMod(timeLong, 1000L) * 1000);\n  }\n\n  @Override\n  public <T> RawValueData<T> getRawValue(int pos) {\n    throw new UnsupportedOperationException(\"Not supported yet.\");\n  }\n\n  @Override\n  public byte[] getBinary(int pos) {\n    return isNullAt(pos) ? null : getBinaryInternal(pos);\n  }\n\n  private byte[] getBinaryInternal(int pos) {","sourceCodeStart":187,"sourceCodeEnd":223,"githubUrl":"https://github.com/apache/iceberg/blob/86d9c8fc543e7c56c9f624eb725f76c9baff9570/flink/v2.2/flink/src/main/java/org/apache/iceberg/flink/data/StructRowData.java#L187-L223","documentation":"For nanosecond-precision timestamps (precision > 6), StructRowData.getTimestamp expects the wrapped StructLike to hold OffsetDateTime, LocalDateTime, or Long (epoch nanos). Encountering any other runtime type means the stored value cannot represent a timestamp_ns field, and IllegalStateException is thrown naming the offending class.","triggerScenarios":"Reading a timestamptz_ns / timestamp_ns Iceberg column through StructRowData when the StructLike stores e.g. a BigDecimal, String, Instant, or micros-Long supplied to a nanos-precision getter.","commonSituations":"Reading tables written by engines that store nanosecond timestamps differently; custom StructLike adapters exposing Instant instead of OffsetDateTime/LocalDateTime; schema promotion from micros to nanos where old data holds a value in the wrong unit/type.","solutions":["Convert the stored value (see the class name in the message) to OffsetDateTime, LocalDateTime, or epoch-nanos Long before it reaches StructRowData.","Confirm the column precision in the read schema matches the physical data; reading nanos data with micros assumptions can feed wrong values.","If using a custom writer, store timestamp_ns as Long epoch-nanos, LocalDateTime, or OffsetDateTime only.","For Instant values, convert with odt = instant.atOffset(ZoneOffset.UTC) before wrapping."],"exampleFix":"// before\nTimestampData ts = structRowData.getTimestamp(pos, 9); // fails for Instant\n\n// after\nObject raw = struct.get(pos, Object.class);\nOffsetDateTime normalized = (raw instanceof Instant i)\n    ? i.atOffset(ZoneOffset.UTC)\n    : (OffsetDateTime) raw;\nTimestampData ts = TimestampData.fromEpochMillis(\n    normalized.toInstant().toEpochMilli(), normalized.getNano() % 1_000_000);","handlingStrategy":"validation","validationCode":"Object raw = struct.get(pos, Object.class);\nPreconditions.checkArgument(\n    precision <= 6 || raw == null || raw instanceof OffsetDateTime\n        || raw instanceof LocalDateTime || raw instanceof Long,\n    \"timestamp_ns field holds unexpected type: %s\", raw == null ? \"null\" : raw.getClass());","typeGuard":"boolean isNanosTimestampRepresentable(Object v) {\n  return v instanceof OffsetDateTime || v instanceof LocalDateTime || v instanceof Long;\n}","tryCatchPattern":"try {\n  TimestampData ts = structRowData.getTimestamp(pos, 9);\n} catch (IllegalStateException e) {\n  if (e.getMessage().startsWith(\"Unknown type for timestamp_ns\")) {\n    log.error(\"Nanos timestamp column stores incompatible type\", e);\n    throw new SchemaMismatchException(e);\n  }\n  throw e;\n}","preventionTips":["Store timestamp_ns values as Long epoch-nanos, LocalDateTime, or OffsetDateTime only.","Match column precision in the read schema to the physical data before scanning."],"tags":["flink","timestamp-ns","type-mismatch","structlike"],"backgroundTag":"type-mismatch","analyzedSha":"86d9c8fc543e7c56c9f624eb725f76c9baff9570","analyzedAt":"2026-09-12T00:46:39.097Z","contentChangedAt":"2026-09-12T00:46:39.097Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}