apache/iceberg · error · IllegalArgumentException

Unexpected object type for DATE logical type. Received: ${ob

Error message

Unexpected object type for DATE logical type. Received: ${object}

What it means

convertToDate converts an Avro DATE logical-type value into an epoch-day int for Flink DATE. If the object is neither LocalDate nor a type the JodaConverter can handle, this IllegalArgumentException is thrown naming the actual object.

Source

Thrown at flink/v1.20/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)

Solutions

  1. Add the joda-time dependency if reading legacy (Joda-era) Avro files, so JodaConverter is available.
  2. Align the DATE field encoding with the modern mapping (LocalDate / days as int) by rewriting the data files.
  3. Inspect the 'Received:' value to identify the class and pre-convert it to LocalDate before conversion.

Example fix

// before
// file stores java.util.Date, joda-time not on classpath -> JodaConverter null
RowData row = converter.convert(record); // throws
// after
// convert Date to LocalDate before reading, or add joda-time dependency
record.put("d", ((java.util.Date) record.get("d")).toInstant().atZone(ZoneOffset.UTC).toLocalDate());
Defensive patterns

Strategy: validation

Validate before calling

Object v = record.get("d");
if (!(v instanceof LocalDate) && !jodaSupported(v)) { throw new IllegalArgumentException("d has unexpected class: " + v.getClass()); }

Type guard

boolean isSupportedDate(Object v) { return v instanceof LocalDate || v instanceof org.joda.time.LocalDate; }

Try / catch

try { return convertToDate(obj); } catch (IllegalArgumentException e) { return (int) toLocalDate(obj).toEpochDay(); }

Prevention

When it happens

Trigger: Avro file stores a DATE field as a Java type outside the expected set (e.g. Integer days without the proper decoder, java.util.Date when Joda classes are absent on the classpath so JodaConverter returns null).

Common situations: Missing joda-time dependency on the classpath so legacy-encoded dates can't be bridged; Avro readers decoding DATE as a different type than the converter expects due to schema/mapping mismatch.

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


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