{"record":{"id":"3ca397159cf9bab2","repo":"apache/iceberg","slug":"cannot-convert-time-value","errorCode":null,"errorMessage":"Cannot convert time: ${value}","messagePattern":"Cannot convert time: (.+?)","errorType":"exception","errorClass":"ConnectException","httpStatus":null,"severity":"error","filePath":"kafka-connect/kafka-connect/src/main/java/org/apache/iceberg/connect/data/RecordConverter.java","lineNumber":568,"sourceCode":"      return DateTimeUtil.dateFromDays(days);\n    }\n    throw new ConnectException(\"Cannot convert date: \" + value);\n  }\n\n  @SuppressWarnings(\"JavaUtilDate\")\n  protected LocalTime convertTimeValue(Object value) {\n    if (value instanceof Number) {\n      long millis = ((Number) value).longValue();\n      return DateTimeUtil.timeFromMicros(millis * 1000);\n    } else if (value instanceof String) {\n      return LocalTime.parse((String) value);\n    } else if (value instanceof LocalTime) {\n      return (LocalTime) value;\n    } else if (value instanceof Date) {\n      long millis = ((Date) value).getTime();\n      return DateTimeUtil.timeFromMicros(millis * 1000);\n    }\n    throw new ConnectException(\"Cannot convert time: \" + value);\n  }\n\n  protected Temporal convertTimestampValue(Object value, TimestampType type) {\n    if (type.shouldAdjustToUTC()) {\n      return convertOffsetDateTime(value);\n    }\n    return convertLocalDateTime(value);\n  }\n\n  protected Variant convertVariantValue(Object value) {\n    if (value instanceof Variant variant) {\n      return variant;\n    }\n\n    List<String> sortedFieldNames =\n        collectFieldNames(value).stream().sorted().collect(Collectors.toList());\n    VariantMetadata metadata = Variants.metadata(sortedFieldNames);\n    return Variant.of(metadata, objectToVariantValue(value, metadata, null));","sourceCodeStart":550,"sourceCodeEnd":586,"githubUrl":"https://github.com/apache/iceberg/blob/86d9c8fc543e7c56c9f624eb725f76c9baff9570/kafka-connect/kafka-connect/src/main/java/org/apache/iceberg/connect/data/RecordConverter.java#L550-L586","documentation":"RecordConverter.convertTimeValue throws this ConnectException when a value mapped to an Iceberg Time column cannot be interpreted as a time. Accepted inputs are Numbers (millis since midnight), Strings (parsed), LocalTime, and java.util.Date; anything else fails.","triggerScenarios":"A Time field receives a struct/map/boolean value; or convertValue/ts passes an unparseable or non-temporal object to convertTimeValue.","commonSituations":"Kafka message contains a JSON object like {\"hour\":10,\"minute\":30} where the table expects time; producer sends epoch millis as a nested payload; schema registry logical type changed from Time to something else.","solutions":["Send the time as epoch millis since midnight (int32) with the Time logical type, or as a parseable string like \"10:30:00\"","Add a TimestampConverter SMT to normalize to Time before the sink","Fix the producer to emit a scalar temporal value instead of a nested object","If the value is truly a timestamp, retarget the Iceberg column to timestamptz instead of time"],"exampleFix":"// before\nproducer value: {\"hour\":10,\"minute\":0} // object -> cannot convert time\n// after\nproducer value: 36000000 // millis since midnight, Time logical type","handlingStrategy":"validation","validationCode":"Object v = record.value().get(\"timeField\");\nif (!(v instanceof Number || v instanceof LocalTime || v instanceof java.util.Date || v instanceof String)) {\n  throw new IllegalStateException(\"Time field bad type: \" + (v == null ? \"null\" : v.getClass()));\n}","typeGuard":"static boolean isTimeCompatible(Object v) {\n  return v == null || v instanceof Number || v instanceof LocalTime\n      || v instanceof java.util.Date || v instanceof String;\n}","tryCatchPattern":"try {\n  converter.convertValue(value, Types.TimeType.get());\n} catch (ConnectException e) {\n  log.error(\"Time conversion failed: \" + e.getMessage(), e);\n  // route to DLQ or coerce to millis-since-midnight number\n}","preventionTips":["Emit time as int32 millis since midnight with Time logical type","Keep producer time format stable (\"HH:mm:ss\" strings also work)","Block nested objects for time fields at the producer","Validate the topic schema against the Iceberg table schema in CI"],"tags":["kafka-connect","time","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"}