apache/seatunnel · error · java.lang.IllegalArgumentException

Unable to convert to LocalDate from a java.sql.Time value '

Error message

Unable to convert to LocalDate from a java.sql.Time value '

What it means

TemporalConversions.toLocalDate(Object) converts supported temporal objects (LocalDate, LocalDateTime, java.sql.Date, java.util.Date, Number epoch) to LocalDate. A java.sql.Time explicitly throws IllegalArgumentException, because a time-of-day cannot be a calendar date. This guards against schema/value mismatches where a TIME value is fed to a DATE field.

Source

Thrown at seatunnel-connectors-v2/connector-cdc/connector-cdc-base/src/main/java/org/apache/seatunnel/connectors/cdc/debezium/utils/TemporalConversions.java:71

    private TemporalConversions() {}

    @SuppressWarnings("MagicNumber")
    public static LocalDate toLocalDate(Object obj) {
        if (obj == null) {
            return null;
        }
        if (obj instanceof LocalDate) {
            return (LocalDate) obj;
        }
        if (obj instanceof LocalDateTime) {
            return ((LocalDateTime) obj).toLocalDate();
        }
        if (obj instanceof java.sql.Date) {
            return ((java.sql.Date) obj).toLocalDate();
        }
        if (obj instanceof java.sql.Time) {
            throw new IllegalArgumentException(
                    "Unable to convert to LocalDate from a java.sql.Time value '" + obj + "'");
        }
        if (obj instanceof java.util.Date) {
            java.util.Date date = (java.util.Date) obj;
            return LocalDate.of(date.getYear() + 1900, date.getMonth() + 1, date.getDate());
        }
        if (obj instanceof Long) {
            if ((Long) obj > ChronoField.EPOCH_DAY.range().getMaximum()) {
                return Instant.ofEpochMilli((Long) obj)
                        .atZone(ZoneId.systemDefault())
                        .toLocalDate();
            }
            // Assume the value is the epoch day number
            return LocalDate.ofEpochDay((Long) obj);
        }
        if (obj instanceof Integer) {
            // Assume the value is the epoch day number
            return LocalDate.ofEpochDay((Integer) obj);

View on GitHub (pinned to cf67b549a7)

Solutions

  1. Align the declared column type with the actual data: declare TIME for the column, or select the intended DATE column.
  2. Convert at source: change the query to cast Time to a Date (e.g. CAST(col AS DATE) or CURDATE-based expression).
  3. Pre-check the object type and route Time values through a toLocalTime() path instead of toLocalDate().

Example fix

// before
LocalDate d = TemporalConversions.toLocalDate(sqlTimeObj); // throws
// after
if (obj instanceof java.sql.Time) {
    LocalTime t = ((java.sql.Time) obj).toLocalTime();
    // handle as time, not date
} else {
    LocalDate d = TemporalConversions.toLocalDate(obj);
}
Defensive patterns

Strategy: type-guard

Validate before calling

// Java
static boolean isConvertibleToDate(Object o) {
    return o instanceof LocalDate || o instanceof LocalDateTime || o instanceof java.sql.Date
        || o instanceof java.util.Date || o instanceof Number;
}

Type guard

if (obj instanceof java.sql.Time) {
    throw new IllegalArgumentException("expected a DATE value, got TIME " + obj);
}
LocalDate d = TemporalConversions.toLocalDate(obj);

Try / catch

try {
    date = TemporalConversions.toLocalDate(value);
} catch (IllegalArgumentException e) {
    log.warn("TIME value fed to DATE field: {}", value);
    date = ((java.sql.Time) value).toLocalTime().atDate(LocalDate.EPOCH); // or route to toLocalTime()
}

Prevention

When it happens

Trigger: Calling TemporalConversions.toLocalDate() with a java.sql.Time argument, typically when a source column's actual JDBC type is TIME but the declared SeaTunnel type is DATE.

Common situations: Schema/type drift: the catalog declares DATE while the CDC value deserialized as TIME; copy connectors mapping a TIME column into a DATE field.

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/seatunnel@cf67b549a7 (2026-09-10). Data as JSON: /api/errors/fc67d0c8cc65dfe6. Report an issue: GitHub.