{"record":{"id":"8b989477c8a3e7c2","repo":"apache/seatunnel","slug":"unable-to-convert-to-localdate-from-a-java-sql-dat","errorCode":null,"errorMessage":"Unable to convert to LocalDate from a java.sql.Date value '","messagePattern":"Unable to convert to LocalDate from a java\\.sql\\.Date value '","errorType":"exception","errorClass":"java.lang.IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"seatunnel-connectors-v2/connector-cdc/connector-cdc-base/src/main/java/org/apache/seatunnel/connectors/cdc/debezium/utils/TemporalConversions.java","lineNumber":109,"sourceCode":"        throw new IllegalArgumentException(\n                \"Unable to convert to LocalDate from unexpected value '\"\n                        + obj\n                        + \"' of type \"\n                        + obj.getClass().getName());\n    }\n\n    public static LocalTime toLocalTime(Object obj) {\n        if (obj == null) {\n            return null;\n        }\n        if (obj instanceof LocalTime) {\n            return (LocalTime) obj;\n        }\n        if (obj instanceof LocalDateTime) {\n            return ((LocalDateTime) obj).toLocalTime();\n        }\n        if (obj instanceof java.sql.Date) {\n            throw new IllegalArgumentException(\n                    \"Unable to convert to LocalDate from a java.sql.Date value '\" + obj + \"'\");\n        }\n        if (obj instanceof java.sql.Time) {\n            java.sql.Time time = (java.sql.Time) obj;\n            long millis = (int) (time.getTime() % MILLISECONDS_PER_SECOND);\n            int nanosOfSecond = (int) (millis * NANOSECONDS_PER_MILLISECOND);\n            return LocalTime.of(\n                    time.getHours(), time.getMinutes(), time.getSeconds(), nanosOfSecond);\n        }\n        if (obj instanceof java.sql.Timestamp) {\n            java.sql.Timestamp timestamp = (java.sql.Timestamp) obj;\n            return LocalTime.of(\n                    timestamp.getHours(),\n                    timestamp.getMinutes(),\n                    timestamp.getSeconds(),\n                    timestamp.getNanos());\n        }\n        if (obj instanceof java.util.Date) {","sourceCodeStart":91,"sourceCodeEnd":127,"githubUrl":"https://github.com/apache/seatunnel/blob/cf67b549a7a6c35fa0beb12d83c62892427ea919/seatunnel-connectors-v2/connector-cdc/connector-cdc-base/src/main/java/org/apache/seatunnel/connectors/cdc/debezium/utils/TemporalConversions.java#L91-L127","documentation":"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.","triggerScenarios":"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.","commonSituations":"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).","solutions":["Fix the column-type mapping so java.sql.Date values go through toLocalDate, not toLocalTime","If midnight is acceptable, convert explicitly: date -> LocalDate -> atStartOfDay().toLocalTime() instead of calling toLocalTime","Correct upstream Debezium config/SMT that changes the column type emitted for this field","Guard the call site by checking the runtime type before conversion"],"exampleFix":"// before\nLocalTime t = TemporalConversions.toLocalTime(sqlDate); // throws\n// after\nLocalDate d = TemporalConversions.toLocalDate(sqlDate, null);\nLocalTime t = d.atStartOfDay().toLocalTime(); // or fix the mapping","handlingStrategy":"type-guard","validationCode":"boolean isConvertibleToTime(Object v) {\n    return v instanceof LocalTime || v instanceof LocalDateTime\n        || v instanceof java.sql.Time || v instanceof Duration\n        || v instanceof String;\n}","typeGuard":"boolean isDateOnly(Object v) {\n    return v instanceof java.sql.Date;\n}","tryCatchPattern":"try {\n    LocalTime t = TemporalConversions.toLocalTime(value);\n} catch (IllegalArgumentException e) {\n    LOG.warn(\"Cannot convert value {} to LocalTime; treating as midnight\", value);\n    return LocalTime.MIDNIGHT;\n}","preventionTips":["Route java.sql.Date values to toLocalDate, never to toLocalTime","Validate column types in schema mapping before deserialization","Check for schema drift (DATE vs TIME) when this appears after source changes","Add a type-dispatch helper wrapping all TemporalConversions calls"],"tags":["java","cdc","time-conversion","type-mismatch"],"backgroundTag":"type-mismatch","analyzedSha":"cf67b549a7a6c35fa0beb12d83c62892427ea919","analyzedAt":"2026-09-10T21:44:55.265Z","contentChangedAt":"2026-09-10T21:44:55.265Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}