{"record":{"id":"e3bd6d221a098fb6","repo":"apache/iceberg","slug":"cannot-convert-timestamp-value-type-value","errorCode":null,"errorMessage":"Cannot convert timestamp: ${value}, type: ${value.getClass()}","messagePattern":"Cannot convert timestamp: (.+?), 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":848,"sourceCode":"          .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);\n    } else if (value instanceof String) {\n      return parseLocalDateTime((String) value);\n    } else if (value instanceof LocalDateTime) {\n      return (LocalDateTime) value;\n    } else if (value instanceof OffsetDateTime) {\n      return ((OffsetDateTime) value).toLocalDateTime();\n    } else if (value instanceof Date) {\n      return DateTimeUtil.timestampFromMicros(((Date) value).getTime() * 1000);\n    }\n    throw new ConnectException(\n        \"Cannot convert timestamp: \" + value + \", type: \" + value.getClass());\n  }\n\n  private LocalDateTime parseLocalDateTime(String str) {\n    String tsStr = ensureTimestampFormat(str);\n    try {\n      return LocalDateTime.parse(tsStr, DateTimeFormatter.ISO_LOCAL_DATE_TIME);\n    } catch (DateTimeParseException e) {\n      return OFFSET_TIMESTAMP_FORMAT.parse(tsStr, OffsetDateTime::from).toLocalDateTime();\n    }\n  }\n\n  private String ensureTimestampFormat(String str) {\n    String result = str;\n    if (result.charAt(10) == ' ') {\n      result = result.substring(0, 10) + 'T' + result.substring(11);\n    }\n    // Search for the timezone offset sign starting after the seconds portion (index 19+).","sourceCodeStart":830,"sourceCodeEnd":866,"githubUrl":"https://github.com/apache/iceberg/blob/86d9c8fc543e7c56c9f624eb725f76c9baff9570/kafka-connect/kafka-connect/src/main/java/org/apache/iceberg/connect/data/RecordConverter.java#L830-L866","documentation":"RecordConverter cannot map the incoming Kafka Connect value to an Iceberg LocalDateTime timestamp. It only accepts LocalDateTime, OffsetDateTime, and java.util.Date; any other object reaching this branch (or null of unexpected type) triggers this ConnectException. It guards Iceberg's timestamp columns from silently wrong types.","triggerScenarios":"Inserting/upserting a Connect record whose schema declares a timestamp but whose logical type was not converted (e.g. io.debezium.time.Timestamp, long epoch millis without a converter, or String dates) into an Iceberg timestamp column via the sink.","commonSituations":"Debezium or custom SMTs emitting epoch-based temporal types that Kafka Connect does not mark as Timestamp logical types; schema evolution changing a field to timestamp while producers still send strings/longs; missing TimestampConverter SMT.","solutions":["Add org.apache.kafka.connect.transforms.TimestampConverter$Value SMT to the connector config to normalize the field to Timestamp type before the sink.","Convert the upstream value to java.util.Date, LocalDateTime, or OffsetDateTime (e.g. a custom SMT).","Check the Iceberg table column type matches the intended timestamp-with/without-zone semantics and fix the topic schema.","If upstream sends epoch millis, wrap with TimestampConverter using type=Timestamp and field=<name>."],"exampleFix":"// before: connector sends Debezium epoch-millis for field 'ts'\n\"transforms.ts.type\": \"org.apache.kafka.connect.transforms.TimestampConverter$Value\",\n\"transforms.ts.field\": \"ts\",\n\"transforms.ts.target.type\": \"Timestamp\"\n// after: RecordConverter sees a Connect Timestamp and converts it via Date branch","handlingStrategy":"validation","validationCode":"if (!(v instanceof LocalDateTime || v instanceof OffsetDateTime || v instanceof Date)) {\n  throw new DataException(\"Field must be timestamp-like, got: \" + v.getClass());\n}","typeGuard":"boolean isTimestampLike(Object v) {\n  return v instanceof LocalDateTime || v instanceof OffsetDateTime || v instanceof Date;\n}","tryCatchPattern":null,"preventionTips":["Add TimestampConverter$Value SMT for temporal fields in connector config","Keep topic schemas using Connect Timestamp logical types","Test converters against Debezium temporal types before production"],"tags":["kafka-connect","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-23T08:17:48.524Z"}