apache/iceberg · error · IllegalArgumentException
Unexpected object type for TIME logical type. Received:
Error message
Unexpected object type for TIME logical type. Received:
What it means
convertToTime throws IllegalArgumentException when the object for an Avro TIME logical type is neither java.time.LocalTime (read via MILLI_OF_DAY) nor a Joda-convertible object (with Joda-Time on classpath), so millis-of-day cannot be extracted.
Source
Thrown at flink/v2.3/flink/src/main/java/org/apache/iceberg/flink/formats/avro/AvroToRowDataConverters.java:284
} else {
throw new IllegalArgumentException(
"Unexpected object type for DATE logical type. Received: " + object);
}
}
}
private static int convertToTime(Object object) {
final int millis;
if (object instanceof Integer) {
millis = (Integer) object;
} else if (object instanceof LocalTime) {
millis = ((LocalTime) object).get(ChronoField.MILLI_OF_DAY);
} else {
JodaConverter jodaConverter = JodaConverter.getConverter();
if (jodaConverter != null) {
millis = jodaConverter.convertTime(object);
} else {
throw new IllegalArgumentException(
"Unexpected object type for TIME logical type. Received: " + object);
}
}
return millis;
}
private static byte[] convertToBytes(Object object) {
if (object instanceof GenericFixed) {
return ((GenericFixed) object).bytes();
} else if (object instanceof ByteBuffer) {
ByteBuffer byteBuffer = (ByteBuffer) object;
byte[] bytes = new byte[byteBuffer.remaining()];
byteBuffer.get(bytes);
return bytes;
} else {
return (byte[]) object;
}
}View on GitHub (pinned to 86d9c8fc54)
Solutions
- Ensure the Avro decoder produces java.time.LocalTime for TIME fields
- Add joda-time dependency for legacy Joda-encoded data
- Pre-convert to millis-of-day before calling the converter
Example fix
// before int millis = convertToTime(legacyDateObject); // throws // after int millis = convertToTime(LocalTime.ofInstant(legacyDateObject.toInstant(), ZoneOffset.UTC));
Defensive patterns
Strategy: type-guard
Validate before calling
if (!(object instanceof LocalTime) && !isJodaTime(object)) { throw new IllegalArgumentException("Expected LocalTime for TIME field, got " + object.getClass()); } Type guard
boolean isTimeDatum(Object o) { return o instanceof LocalTime || o instanceof org.joda.time.LocalTime; } Try / catch
try { return convertToTime(object); } catch (IllegalArgumentException e) { log.error("Bad TIME datum class: {}", object.getClass()); throw e; } Prevention
- Verify the Avro time-millis/time-micros decoder returns LocalTime
- Keep joda-time available for legacy data
- Run one end-to-end read of representative data before scaling
When it happens
Trigger: Avro datum for time fields is a java.util.Date, Instant, Long, or other non-LocalTime class; Joda converter null when data holds Joda LocalTime objects.
Common situations: Cross-version Avro data where time is encoded as millis long or util.Date; missing joda-time dependency.
Understand the failure class
Background: Type mismatch errors: IllegalArgumentException, TypeError and type guards across 150 open-source libraries — this error's family across 150 libraries.
Related errors
- Unexpected object type for TIME logical type. Received: ${ob
- Unexpected object type for TIME logical type. Received: ${ob
- Unexpected object type for TIME logical type. Received: " +
- Unexpected object type for TIMESTAMP logical type. Received:
- Unexpected object type for DATE logical type. Received:
AI-assisted analysis of apache/iceberg@86d9c8fc54 (2026-09-12).
Data as JSON: /api/errors/3d708146f7dc33d0.
Report an issue: GitHub.