{"record":{"id":"fd6e00a1d79d709d","repo":"apache/iceberg","slug":"cannot-convert-timestamptz-value-type-valu","errorCode":null,"errorMessage":"Cannot convert timestamptz: ${value}, type: ${value.getClass()}","messagePattern":"Cannot convert timestamptz: (.+?), type: (.+?)","errorType":"exception","errorClass":"ConnectException","httpStatus":null,"severity":"error","filePath":"kafka-connect/kafka-connect/src/main/java/org/apache/iceberg/connect/data/RecordConverter.java","lineNumber":820,"sourceCode":"    throw new IllegalArgumentException(\n        \"Cannot convert Number to variant (unknown type): \" + number.getClass().getName());\n  }\n\n  @SuppressWarnings(\"JavaUtilDate\")\n  private OffsetDateTime convertOffsetDateTime(Object value) {\n    if (value instanceof Number) {\n      long millis = ((Number) value).longValue();\n      return DateTimeUtil.timestamptzFromMicros(millis * 1000);\n    } else if (value instanceof String) {\n      return parseOffsetDateTime((String) value);\n    } else if (value instanceof OffsetDateTime) {\n      return (OffsetDateTime) value;\n    } else if (value instanceof LocalDateTime) {\n      return ((LocalDateTime) value).atOffset(ZoneOffset.UTC);\n    } else if (value instanceof Date) {\n      return DateTimeUtil.timestamptzFromMicros(((Date) value).getTime() * 1000);\n    }\n    throw new ConnectException(\n        \"Cannot convert timestamptz: \" + value + \", type: \" + value.getClass());\n  }\n\n  private OffsetDateTime parseOffsetDateTime(String str) {\n    String tsStr = ensureTimestampFormat(str);\n    try {\n      return OFFSET_TIMESTAMP_FORMAT.parse(tsStr, OffsetDateTime::from);\n    } catch (DateTimeParseException e) {\n      return LocalDateTime.parse(tsStr, DateTimeFormatter.ISO_LOCAL_DATE_TIME)\n          .atOffset(ZoneOffset.UTC);\n    }\n  }\n\n  @SuppressWarnings(\"JavaUtilDate\")\n  private LocalDateTime convertLocalDateTime(Object value) {\n    if (value instanceof Number) {\n      long millis = ((Number) value).longValue();\n      return DateTimeUtil.timestampFromMicros(millis * 1000);","sourceCodeStart":802,"sourceCodeEnd":838,"githubUrl":"https://github.com/apache/iceberg/blob/86d9c8fc543e7c56c9f624eb725f76c9baff9570/kafka-connect/kafka-connect/src/main/java/org/apache/iceberg/connect/data/RecordConverter.java#L802-L838","documentation":"convertOffsetDateTime (the timestamptz conversion path in RecordConverter) throws this ConnectException when a value for an Iceberg timestamptz column is not a Number (epoch micros/millis), String (parseable timestamp), OffsetDateTime, LocalDateTime, or java.util.Date. The message includes both the value and its concrete class to aid diagnosis.","triggerScenarios":"A timestamptz field receives a struct/map/boolean or an unparseable string via convertValue/ts; recursion hits an object type with no conversion branch.","commonSituations":"Producer sends nested JSON timestamp objects; ISO strings with offsets the parser rejects after ensureTimestampFormat normalization; schemaless records delivering unexpected wrappers; SMTs converting timestamps to non-temporal types.","solutions":["Send timestamps as epoch-millis Numbers, ISO-8601 strings, or use Connect's Timestamp logical type (java.util.Date)","Use TimestampConverter SMT to normalize the field before the sink","Log the value/class from the message and correct the producer's serialization","If the column should hold a different type, adjust the Iceberg schema or field mapping"],"exampleFix":"// before\nvalue = {\"date\":\"2024-01-01\",\"time\":\"10:00:00\"} // nested object\n// after\nvalue = 1704112800000L // epoch millis, or \"2024-01-01T10:00:00+00:00\" string","handlingStrategy":"validation","validationCode":"Object v = record.value().get(\"tsField\");\nboolean ok = v == null || v instanceof Number || v instanceof String || v instanceof OffsetDateTime\n    || v instanceof LocalDateTime || v instanceof java.util.Date;\nif (!ok) throw new IllegalStateException(\"timestamptz field bad type: \" + v.getClass());","typeGuard":"static boolean isTimestamptzCompatible(Object v) {\n  return v == null || v instanceof Number || v instanceof String || v instanceof OffsetDateTime\n      || v instanceof LocalDateTime || v instanceof java.util.Date;\n}","tryCatchPattern":"try {\n  converter.convertValue(value, Types.TimestampType.withZone());\n} catch (ConnectException e) {\n  if (e.getMessage().startsWith(\"Cannot convert timestamptz:\")) {\n    log.error(\"Bad timestamptz value: \" + e.getMessage());\n    // DLQ the record or normalize with TimestampConverter before retry\n  }\n}","preventionTips":["Emit timestamps as epoch millis or ISO-8601 strings with explicit offset","Use Connect Timestamp logical type for java.util.Date values","Run TimestampConverter SMT to normalize formats","Pin timestamp format in producer contracts and validate in CI"],"tags":["kafka-connect","timestamp","type-mismatch"],"backgroundTag":"invalid-date-format","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"}