{"record":{"id":"0f47b8beffb1ffeb","repo":"apache/iceberg","slug":"unexpected-object-type-for-time-logical-type-rece-0f47b8","errorCode":null,"errorMessage":"Unexpected object type for TIME logical type. Received: ${object}","messagePattern":"Unexpected object type for TIME logical type\\. Received: (.+?)","errorType":"exception","errorClass":"java.lang.IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"flink/v2.1/flink/src/main/java/org/apache/iceberg/flink/formats/avro/AvroToRowDataConverters.java","lineNumber":284,"sourceCode":"      } else {\n        throw new IllegalArgumentException(\n            \"Unexpected object type for DATE logical type. Received: \" + object);\n      }\n    }\n  }\n\n  private static int convertToTime(Object object) {\n    final int millis;\n    if (object instanceof Integer) {\n      millis = (Integer) object;\n    } else if (object instanceof LocalTime) {\n      millis = ((LocalTime) object).get(ChronoField.MILLI_OF_DAY);\n    } else {\n      JodaConverter jodaConverter = JodaConverter.getConverter();\n      if (jodaConverter != null) {\n        millis = jodaConverter.convertTime(object);\n      } else {\n        throw new IllegalArgumentException(\n            \"Unexpected object type for TIME logical type. Received: \" + object);\n      }\n    }\n    return millis;\n  }\n\n  private static byte[] convertToBytes(Object object) {\n    if (object instanceof GenericFixed) {\n      return ((GenericFixed) object).bytes();\n    } else if (object instanceof ByteBuffer) {\n      ByteBuffer byteBuffer = (ByteBuffer) object;\n      byte[] bytes = new byte[byteBuffer.remaining()];\n      byteBuffer.get(bytes);\n      return bytes;\n    } else {\n      return (byte[]) object;\n    }\n  }","sourceCodeStart":266,"sourceCodeEnd":302,"githubUrl":"https://github.com/apache/iceberg/blob/86d9c8fc543e7c56c9f624eb725f76c9baff9570/flink/v2.1/flink/src/main/java/org/apache/iceberg/flink/formats/avro/AvroToRowDataConverters.java#L266-L302","documentation":"Thrown by AvroToRowDataConverters.convertToTime when an Avro 'time-millis'/'time-micros' logical type field yields an object that is neither java.time.LocalTime nor a Joda-convertible type. The converter needs to extract millis-of-day but cannot from the unexpected object type.","triggerScenarios":"Reading Avro records where a time logical-type field arrives as java.util.Date, String, Long, etc., and JodaConverter is null (joda-time not on the classpath) or cannot handle the type.","commonSituations":"Legacy Avro writers producing time fields as Joda or util types; java.time-based Flink reads with missing joda-time dependency; schema mismatch dropping the logical type so raw Longs arrive.","solutions":["Ensure the Avro schema retains the time logical type and the reader materializes java.time.LocalTime","Add joda-time dependency if consuming legacy Joda-based records","Pre-convert the field to LocalTime before the record enters the Avro reader pipeline","Verify the writer schema logical types match what the reader expects"],"exampleFix":"// before: time arrives as Long millis\nint millis = ((Long) obj).intValue();\n// after: convert to LocalTime so the converter accepts it\nLocalTime t = LocalTime.ofNanoOfDay(((Long) obj) * 1_000_000);","handlingStrategy":"type-guard","validationCode":"Object t = record.get(\"time\");\nif (!(t instanceof LocalTime)) {\n  throw new IllegalStateException(\"Time field must be LocalTime, got: \" + t.getClass());\n}","typeGuard":"boolean isLocalTime(Object o) {\n  return o instanceof LocalTime;\n}","tryCatchPattern":"try {\n  RowData row = converter.convert(record);\n} catch (IllegalArgumentException e) {\n  if (e.getMessage().contains(\"Unexpected object type for TIME\")) {\n    // normalize to LocalTime and retry\n  } else { throw e; }\n}","preventionTips":["Keep time logical types declared in the schema","Ensure readers materialize java.time.LocalTime","Include joda-time when bridging legacy Joda data","Test deserialization of all logical-type fields"],"tags":["flink","avro","time","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-14T16:17:12.679Z"}