apache/iceberg · error · ConnectException
Cannot convert time
Error message
Cannot convert time: ${value} What it means
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.
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
Example fix
// before
producer value: {"hour":10,"minute":0} // object -> cannot convert time
// after
producer value: 36000000 // millis since midnight, Time logical type Defensive patterns
Strategy: validation
Validate before calling
Object v = record.value().get("timeField");
if (!(v instanceof Number || v instanceof LocalTime || v instanceof java.util.Date || v instanceof String)) {
throw new IllegalStateException("Time field bad type: " + (v == null ? "null" : v.getClass()));
} Type guard
static boolean isTimeCompatible(Object v) {
return v == null || v instanceof Number || v instanceof LocalTime
|| v instanceof java.util.Date || v instanceof String;
} Try / catch
try {
converter.convertValue(value, Types.TimeType.get());
} catch (ConnectException e) {
log.error("Time conversion failed: " + e.getMessage(), e);
// route to DLQ or coerce to millis-since-midnight number
} Prevention
- 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
When it happens
Trigger: A Time field receives a struct/map/boolean value; or convertValue/ts passes an unparseable or non-temporal object to convertTimeValue.
Common situations: 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.
Related errors
- Cannot convert date
- Cannot convert timestamp
- Cannot convert timestamptz
- Cannot convert to binary
- Cannot convert to double
AI-assisted analysis of apache/iceberg@86d9c8fc54 (2026-09-12).
Data as JSON: /api/errors/3ca397159cf9bab2.
Report an issue: GitHub.
Appendix: source
Thrown at kafka-connect/kafka-connect/src/main/java/org/apache/iceberg/connect/data/RecordConverter.java:568
return DateTimeUtil.dateFromDays(days);
}
throw new ConnectException("Cannot convert date: " + value);
}
@SuppressWarnings("JavaUtilDate")
protected LocalTime convertTimeValue(Object value) {
if (value instanceof Number) {
long millis = ((Number) value).longValue();
return DateTimeUtil.timeFromMicros(millis * 1000);
} else if (value instanceof String) {
return LocalTime.parse((String) value);
} else if (value instanceof LocalTime) {
return (LocalTime) value;
} else if (value instanceof Date) {
long millis = ((Date) value).getTime();
return DateTimeUtil.timeFromMicros(millis * 1000);
}
throw new ConnectException("Cannot convert time: " + value);
}
protected Temporal convertTimestampValue(Object value, TimestampType type) {
if (type.shouldAdjustToUTC()) {
return convertOffsetDateTime(value);
}
return convertLocalDateTime(value);
}
protected Variant convertVariantValue(Object value) {
if (value instanceof Variant variant) {
return variant;
}
List<String> sortedFieldNames =
collectFieldNames(value).stream().sorted().collect(Collectors.toList());
VariantMetadata metadata = Variants.metadata(sortedFieldNames);
return Variant.of(metadata, objectToVariantValue(value, metadata, null));View on GitHub (pinned to 86d9c8fc54)