apache/seatunnel · error · java.lang.IllegalArgumentException

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

Error message

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

What it means

TemporalConversions.toLocalTime converts time-like objects into java.time.LocalTime, but a java.sql.Date carries only a date (no time-of-day information), so it is unconvertible. The library explicitly throws this IllegalArgumentException instead of silently returning midnight. The message text mistakenly says 'LocalDate' (a copy-paste bug) but the operation is toLocalTime.

Source

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

        throw new IllegalArgumentException(
                "Unable to convert to LocalDate from unexpected value '"
                        + obj
                        + "' of type "
                        + obj.getClass().getName());
    }

    public static LocalTime toLocalTime(Object obj) {
        if (obj == null) {
            return null;
        }
        if (obj instanceof LocalTime) {
            return (LocalTime) obj;
        }
        if (obj instanceof LocalDateTime) {
            return ((LocalDateTime) obj).toLocalTime();
        }
        if (obj instanceof java.sql.Date) {
            throw new IllegalArgumentException(
                    "Unable to convert to LocalDate from a java.sql.Date value '" + obj + "'");
        }
        if (obj instanceof java.sql.Time) {
            java.sql.Time time = (java.sql.Time) obj;
            long millis = (int) (time.getTime() % MILLISECONDS_PER_SECOND);
            int nanosOfSecond = (int) (millis * NANOSECONDS_PER_MILLISECOND);
            return LocalTime.of(
                    time.getHours(), time.getMinutes(), time.getSeconds(), nanosOfSecond);
        }
        if (obj instanceof java.sql.Timestamp) {
            java.sql.Timestamp timestamp = (java.sql.Timestamp) obj;
            return LocalTime.of(
                    timestamp.getHours(),
                    timestamp.getMinutes(),
                    timestamp.getSeconds(),
                    timestamp.getNanos());
        }
        if (obj instanceof java.util.Date) {

View on GitHub (pinned to cf67b549a7)

Solutions

  1. Fix the column-type mapping so java.sql.Date values go through toLocalDate, not toLocalTime
  2. If midnight is acceptable, convert explicitly: date -> LocalDate -> atStartOfDay().toLocalTime() instead of calling toLocalTime
  3. Correct upstream Debezium config/SMT that changes the column type emitted for this field
  4. Guard the call site by checking the runtime type before conversion

Example fix

// before
LocalTime t = TemporalConversions.toLocalTime(sqlDate); // throws
// after
LocalDate d = TemporalConversions.toLocalDate(sqlDate, null);
LocalTime t = d.atStartOfDay().toLocalTime(); // or fix the mapping
Defensive patterns

Strategy: type-guard

Validate before calling

boolean isConvertibleToTime(Object v) {
    return v instanceof LocalTime || v instanceof LocalDateTime
        || v instanceof java.sql.Time || v instanceof Duration
        || v instanceof String;
}

Type guard

boolean isDateOnly(Object v) {
    return v instanceof java.sql.Date;
}

Try / catch

try {
    LocalTime t = TemporalConversions.toLocalTime(value);
} catch (IllegalArgumentException e) {
    LOG.warn("Cannot convert value {} to LocalTime; treating as midnight", value);
    return LocalTime.MIDNIGHT;
}

Prevention

When it happens

Trigger: Calling toLocalTime/localTime with a java.sql.Date object — typically when a DATE column value is fed into time conversion code, or column type inference mapped a date column to a time field.

Common situations: Schema drift where the source column changed from TIME to DATE; a generic row-deserializer that routes all java.sql.* temporal values to toLocalTime; misconfigured CDC table mapping (reading a date column as a TIME column).

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/8b989477c8a3e7c2. Report an issue: GitHub.