{"record":{"id":"ae18d96c3c4ad82f","repo":"apache/iceberg","slug":"unknown-type-for-timestamp-ns-class","errorCode":null,"errorMessage":"Unknown type for timestamp_ns: ${class}","messagePattern":"Unknown type for timestamp_ns: (.+?)","errorType":"exception","errorClass":"IllegalStateException","httpStatus":null,"severity":"error","filePath":"flink/v1.20/flink/src/main/java/org/apache/iceberg/flink/data/StructRowData.java","lineNumber":204,"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":186,"sourceCodeEnd":222,"githubUrl":"https://github.com/apache/iceberg/blob/86d9c8fc543e7c56c9f624eb725f76c9baff9570/flink/v1.20/flink/src/main/java/org/apache/iceberg/flink/data/StructRowData.java#L186-L222","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before: value stored as OffsetDateTime, field projected as TIMESTAMP(9) (local)\nschema.add(\"ts\", Types.TimestampType.withoutZone()); // reader emits OffsetDateTime -> throws\n// after: read with withZone() type, or convert to LocalDateTime before projection\nschema.add(\"ts\", Types.TimestampType.withZone());","handlingStrategy":"type-guard","validationCode":"if (!(v instanceof LocalDateTime || v instanceof Long)) {\n  throw new IllegalArgumentException(\"value not timestamp_ns-compatible: \" + v.getClass());\n}","typeGuard":"boolean isTimestampNsCompatible(Object v) {\n  return v instanceof LocalDateTime || v instanceof Long;\n}","tryCatchPattern":"try {\n  TimestampData ts = structRow.getTimestamp(pos, 9);\n} catch (IllegalStateException e) {\n  if (e.getMessage().startsWith(\"Unknown type for timestamp_ns\")) {\n    // convert to LocalDateTime/epoch-nanos or correct the withZone/withoutZone mapping\n  }\n}","preventionTips":["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"],"tags":["flink","rowdata","timestamp","type-mismatch"],"backgroundTag":"type-mismatch","analyzedSha":"86d9c8fc543e7c56c9f624eb725f76c9baff9570","analyzedAt":"2026-09-12T00:46:39.097Z","contentChangedAt":"2026-09-12T00:46:39.097Z","schemaVersion":2},"datasetVersion":"2026-09-14T16:17:12.679Z"}