apache/iceberg · error · IllegalArgumentException
Unexpected object type for TIME logical type. Received: " +
Error message
Unexpected object type for TIME logical type. Received: " + object
What it means
convertToTime converts the Avro-decoded object for a TIME logical type into millis-of-day int. It supports java.time.LocalTime and Joda objects via JodaConverter; otherwise it throws IllegalArgumentException("Unexpected object type for TIME logical type. Received: " + object). It indicates the runtime decoded object doesn't match the TIME logical type.
Source
Thrown at flink/v2.2/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 schema declares the time logicalType so decoding yields LocalTime.
- Add joda-time to the runtime classpath for legacy Joda-encoded times.
- Align the Flink column type (e.g. INT/TIME) with what the data actually contains.
Example fix
// before
{ "name": "t", "type": "int" } // decoded as Integer
// after
{ "name": "t", "type": { "type": "int", "logicalType": "time-millis" } } Defensive patterns
Strategy: type-guard
Validate before calling
if (!(avroObject instanceof LocalTime) && JodaConverter.getConverter() == null) { throw new IllegalStateException("TIME field decodes to " + avroObject.getClass() + " and Joda converter unavailable"); } Type guard
boolean isSupportedTimeObject(Object o) { return o instanceof LocalTime || (isJodaTime(o) && JodaConverter.getConverter() != null); } Try / catch
try { int millis = convertToTime(avroObject); } catch (IllegalArgumentException e) { /* inspect received type in message */ } Prevention
- Ensure Avro schemas declare time-millis/time-micros logicalType for time fields.
- Include joda-time when consuming legacy-encoded times.
- Round-trip test Avro serialize/deserialize for time columns.
When it happens
Trigger: An Avro 'time-millis'/'time-micros' field decodes to an unexpected object (e.g. plain int because the schema omitted the logical type), or Joda data with joda-time missing from the runtime.
Common situations: Schema evolution where the producer dropped the time logicalType; missing joda-time dependency; hand-built Avro GenericRecord values bypassing logical type conversion.
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: ${ob
AI-assisted analysis of apache/iceberg@86d9c8fc54 (2026-09-12).
Data as JSON: /api/errors/bfb5fa90aa40b184.
Report an issue: GitHub.