{"record":{"id":"9e92449914ab0b83","repo":"apache/seatunnel","slug":"unable-to-convert-to-localdate-from-unexpected-val","errorCode":null,"errorMessage":"Unable to convert to LocalDate from unexpected value '' of type ","messagePattern":"Unable to convert to LocalDate from unexpected value '' of type ","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":91,"sourceCode":"        }\n        if (obj instanceof java.util.Date) {\n            java.util.Date date = (java.util.Date) obj;\n            return LocalDate.of(date.getYear() + 1900, date.getMonth() + 1, date.getDate());\n        }\n        if (obj instanceof Long) {\n            if ((Long) obj > ChronoField.EPOCH_DAY.range().getMaximum()) {\n                return Instant.ofEpochMilli((Long) obj)\n                        .atZone(ZoneId.systemDefault())\n                        .toLocalDate();\n            }\n            // Assume the value is the epoch day number\n            return LocalDate.ofEpochDay((Long) obj);\n        }\n        if (obj instanceof Integer) {\n            // Assume the value is the epoch day number\n            return LocalDate.ofEpochDay((Integer) obj);\n        }\n        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(","sourceCodeStart":73,"sourceCodeEnd":109,"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#L73-L109","documentation":"TemporalConversions.toLocalDate converts Debezium/UTC date representations (String, java.util.Date, Long, Integer) into a java.time.LocalDate. When the incoming object is none of the supported types, the method throws this IllegalArgumentException naming the value and its actual class. It signals a mismatch between the source column type and the type the deserializer produced.","triggerScenarios":"Calling toLocalDate (directly or via localDate) with an object that is not a String, java.util.Date, java.sql.Date, Long, or Integer — e.g. a java.sql.Timestamp, a ByteBuffer/microseconds value, or a custom struct returned by Debezium for a DATE column.","commonSituations":"CDC reading a DATE column whose converter was not configured (Debezium delivers io.debezium.time.Date as int32 normally, but a schema change or custom SMT yields an unexpected type); using a newer/older Debezium version that changed the emitted type; passing a Timestamp where a date-only value was expected.","solutions":["Inspect the logged class name in the message and add/fix a converter (e.g. a custom SourceTimestampConverter or Debezium converter) so DATE columns are delivered as Integer/Long epoch days or ISO String","Check the Debezium connector's time.precision.mode and 'converters' config; ensure DATE columns map to a supported type","Upgrade or align the connector-cdc-base/Debezium versions so types match what TemporalConversions supports","Pre-convert the value yourself before calling toLocalDate, e.g. unwrap Timestamp or decode micros to epoch days"],"exampleFix":"// before\nObject value = struct.get(\"birth_date\"); // java.sql.Timestamp\nLocalDate d = TemporalConversions.toLocalDate(value, null); // throws\n// after\nLocalDate d;\nif (value instanceof java.sql.Timestamp) {\n    d = ((java.sql.Timestamp) value).toLocalDateTime().toLocalDate();\n} else {\n    d = TemporalConversions.toLocalDate(value, null);\n}","handlingStrategy":"type-guard","validationCode":"boolean isConvertibleToDate(Object v) {\n    return v instanceof String || v instanceof java.util.Date\n        || v instanceof Long || v instanceof Integer;\n}","typeGuard":"boolean isEpochDay(Object v) {\n    return v instanceof Long || v instanceof Integer;\n}","tryCatchPattern":"try {\n    LocalDate d = TemporalConversions.toLocalDate(value, null);\n} catch (IllegalArgumentException e) {\n    LOG.warn(\"Unconvertible DATE value {} ({}), skipping row\", value,\n        value == null ? \"null\" : value.getClass().getName(), e);\n}","preventionTips":["Log value.getClass().getName() before conversion in new connectors","Register Debezium time converters in the connector config","Pin compatible SeaTunnel connector-cdc and Debezium versions","Unit-test conversions against the actual wire types your source emits"],"tags":["java","cdc","date-conversion","type-mismatch"],"backgroundTag":"invalid-argument-value","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"}