apache/iceberg · error · IllegalArgumentException

Unexpected object type for DATE logical type. Received: " +…

Error message

Unexpected object type for DATE logical type. Received: " + object

What it means

convertToDate converts the Avro-decoded object for a DATE logical type into epoch-day int. It supports java.time.LocalDate and Joda-readable objects (when JodaConverter is available); anything else raises IllegalArgumentException("Unexpected object type for DATE logical type. Received: " + object). It fires when the runtime object doesn't match the declared DATE logical type.

Solutions

  1. Ensure the producer's Avro schema applies the 'date' logical type so the decoder yields LocalDate.
  2. Add joda-time to the classpath if consuming legacy Joda-encoded data.
  3. Check the printed object type in the message and align the Flink column type (e.g. INT for raw day counts).

Example fix

// before
{ "name": "d", "type": "int" } // no logicalType
// after
{ "name": "d", "type": { "type": "int", "logicalType": "date" } }
Defensive patterns

Strategy: type-guard

Validate before calling

if (!(avroObject instanceof LocalDate) && JodaConverter.getConverter() == null) { throw new IllegalStateException("DATE field decodes to " + avroObject.getClass() + " and Joda converter unavailable"); }

Type guard

boolean isSupportedDateObject(Object o) { return o instanceof LocalDate || (isJodaDate(o) && JodaConverter.getConverter() != null); }

Try / catch

try { int day = convertToDate(avroObject); } catch (IllegalArgumentException e) { /* log object class, fix schema or converter */ }

Prevention

When it happens

Trigger: An Avro field with date logical type decodes to an unexpected object (e.g. Integer millis because the schema declared int without the date logical type, or a String date), or Joda converter is unavailable for legacy Joda-encoded dates.

Common situations: Avro schema/actual data mismatch: producer writes plain int but consumer schema declares Avro 'date'; missing joda-time dependency; custom decoders bypassing logical-type conversion.

Related errors


AI-assisted analysis of apache/iceberg@86d9c8fc54 (2026-09-12). Data as JSON: /api/errors/9d7e4ca7d535e97b. Report an issue: GitHub.

Appendix: source

Thrown at flink/v2.2/flink/src/main/java/org/apache/iceberg/flink/formats/avro/AvroToRowDataConverters.java:267

        return TimestampData.fromEpochMillis(jodaConverter.convertTimestamp(object));
      } else {
        throw new IllegalArgumentException(
            "Unexpected object type for TIMESTAMP logical type. Received: " + object);
      }
    }
  }

  private static int convertToDate(Object object) {
    if (object instanceof Integer) {
      return (Integer) object;
    } else if (object instanceof LocalDate) {
      return (int) ((LocalDate) object).toEpochDay();
    } else {
      JodaConverter jodaConverter = JodaConverter.getConverter();
      if (jodaConverter != null) {
        return (int) jodaConverter.convertDate(object);
      } 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);

View on GitHub (pinned to 86d9c8fc54)