{"record":{"id":"af36e317e1855e29","repo":"apache/iceberg","slug":"unexpected-object-type-for-timestamp-logical-type-af36e3","errorCode":null,"errorMessage":"Unexpected object type for TIMESTAMP logical type. Received: \" + object","messagePattern":"Unexpected object type for TIMESTAMP logical type\\. Received: \" \\+ object","errorType":"exception","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"flink/v2.2/flink/src/main/java/org/apache/iceberg/flink/formats/avro/AvroToRowDataConverters.java","lineNumber":251,"sourceCode":"        return TimestampData.fromEpochMillis(timeLong);\n      } else if (precision <= 6) {\n        return TimestampData.fromEpochMillis(\n            Math.floorDiv(timeLong, 1000L), (int) Math.floorMod(timeLong, 1000L) * 1000);\n      } else {\n        // Iceberg: Added support for nanoseconds precision (FLINK-39251)\n        return TimestampData.fromEpochMillis(\n            Math.floorDiv(timeLong, 1_000_000L), (int) Math.floorMod(timeLong, 1_000_000L));\n      }\n    } else if (object instanceof Instant) {\n      return TimestampData.fromInstant((Instant) object);\n    } else if (object instanceof LocalDateTime) {\n      return TimestampData.fromLocalDateTime((LocalDateTime) object);\n    } else {\n      JodaConverter jodaConverter = JodaConverter.getConverter();\n      if (jodaConverter != null) {\n        return TimestampData.fromEpochMillis(jodaConverter.convertTimestamp(object));\n      } else {\n        throw new IllegalArgumentException(\n            \"Unexpected object type for TIMESTAMP logical type. Received: \" + object);\n      }\n    }\n  }\n\n  private static int convertToDate(Object object) {\n    if (object instanceof Integer) {\n      return (Integer) object;\n    } else if (object instanceof LocalDate) {\n      return (int) ((LocalDate) object).toEpochDay();\n    } else {\n      JodaConverter jodaConverter = JodaConverter.getConverter();\n      if (jodaConverter != null) {\n        return (int) jodaConverter.convertDate(object);\n      } else {\n        throw new IllegalArgumentException(\n            \"Unexpected object type for DATE logical type. Received: \" + object);\n      }","sourceCodeStart":233,"sourceCodeEnd":269,"githubUrl":"https://github.com/apache/iceberg/blob/86d9c8fc543e7c56c9f624eb725f76c9baff9570/flink/v2.2/flink/src/main/java/org/apache/iceberg/flink/formats/avro/AvroToRowDataConverters.java#L233-L269","documentation":"convertToTimestamp converts the Avro-decoded object for a TIMESTAMP logical type into TimestampData. It accepts java.time.LocalDateTime and (via JodaConverter, if on the classpath) Joda-time objects; any other object type triggers IllegalArgumentException(\"Unexpected object type for TIMESTAMP logical type. Received: \" + object). This happens when the Avro record's actual runtime type doesn't match the declared logical type.","triggerScenarios":"An Avro field declared as timestamp logical type decodes to neither LocalDateTime nor a Joda-supported type — e.g. a java.time.Instant arriving in a converter path expecting LocalDateTime, or the Joda converter returning null because Joda classes are absent.","commonSituations":"Mixing timestamp-millis/micros (Instant-backed) Avro fields with a WITHOUT_TIME_ZONE RowData converter; missing Joda-time dependency in the runtime so JodaConverter.getConverter() returns null; producer writing a different Avro schema than declared.","solutions":["Align the Avro field's logical type with the Flink type: use TIMESTAMP_WITH_LOCAL_TIME_ZONE for Instant-backed fields.","Ensure joda-time is on the classpath if consuming legacy Avro data.","Inspect the received object printed in the message and add/fix the converter path for that type."],"exampleFix":"// before\nDataTypes.TIMESTAMP(3) // for Avro timestamp-millis (Instant)\n// after\nDataTypes.TIMESTAMP_WITH_LOCAL_TIME_ZONE(3)","handlingStrategy":"type-guard","validationCode":"// ensure joda-time is present when legacy Avro data is expected\nClass.forName(\"org.joda.time.DateTime\");","typeGuard":"boolean isSupportedTimestampObject(Object o) { return o instanceof LocalDateTime || (o instanceof org.joda.time.DateTime && JodaConverter.getConverter() != null); }","tryCatchPattern":"try { TimestampData ts = convertToTimestamp(avroObject, type); } catch (IllegalArgumentException e) { /* inspect e.getMessage() for the actual runtime type */ }","preventionTips":["Match Avro logical types to Flink types: timestamp-millis/micros (Instant) -> TIMESTAMP_WITH_LOCAL_TIME_ZONE.","Keep joda-time on the classpath for legacy Avro data.","Validate Avro schemas against the Flink schema at job startup."],"tags":["flink","avro","timestamp","type-mismatch"],"backgroundTag":"unexpected-response-shape","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"}