{"record":{"id":"3e627faaead1b505","repo":"apache/seatunnel","slug":"unable-to-convert-to-localdatetime-from-unexpected-3e627f","errorCode":null,"errorMessage":"Unable to convert to LocalDateTime from unexpected value '' of type ","messagePattern":"Unable to convert to LocalDateTime 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":222,"sourceCode":"                millis = MILLISECONDS_PER_SECOND + millis;\n            }\n            int nanosOfSecond = (int) (millis * NANOSECONDS_PER_MILLISECOND);\n            return LocalDateTime.of(\n                    date.getYear() + 1900,\n                    date.getMonth() + 1,\n                    date.getDate(),\n                    date.getHours(),\n                    date.getMinutes(),\n                    date.getSeconds(),\n                    nanosOfSecond);\n        }\n        if (obj instanceof String) {\n            String str = (String) obj;\n            // TIMESTAMP type is encoded in string type\n            Instant instant = Instant.parse(str);\n            return LocalDateTime.ofInstant(instant, serverTimeZone);\n        }\n        throw new IllegalArgumentException(\n                \"Unable to convert to LocalDateTime from unexpected value '\"\n                        + obj\n                        + \"' of type \"\n                        + obj.getClass().getName());\n    }\n}\n","sourceCodeStart":204,"sourceCodeEnd":229,"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#L204-L229","documentation":"toLocalDateTime converts timestamp-like values into java.time.LocalDateTime, supporting Long (epoch millis/micros depending on overload), java.util.Date, java.sql.Timestamp, LocalDateTime, and ISO-8601 Instant strings parsed against the server time zone. When the object matches none of these, the method throws this IllegalArgumentException naming the value and its class. It means the TIMESTAMP column's wire representation is not what the converter expects.","triggerScenarios":"Calling toLocalDateTime with an unsupported object — e.g. a java.sql.Date, a BigDecimal from high-precision DECIMAL-encoded timestamps, a Debezium Struct field left unwrapped, or a non-ISO String (e.g. 'yyyy-MM-dd HH:mm:ss' without 'T'/offset) that fails Instant.parse before the typed branches.","commonSituations":"Source database TIMESTAMP stored/replicated in a non-ISO string format; MySQL/Postgres CDC delivering microseconds (io.debezium.time.MicroTimestamp) while code calls the millis overload; timezone misconfiguration producing unexpected types; schema evolution changing the column representation.","solutions":["Log/inspect the class in the message and pre-normalize the value (e.g. reformat 'yyyy-MM-dd HH:mm:ss' strings to ISO-8601 with 'T' before calling, or use the correct Long overload for micros vs millis)","Check the toLocalDateTime overload used: pass the right TimeUnit/ZoneId so Debezium micros-based timestamps are converted correctly","Configure Debezium time converters (io.debezium.converters.*) so TIMESTAMP columns arrive as a supported type","Align connector-cdc-base version with the Debezium connector version in use"],"exampleFix":"// before\nString raw = \"2024-01-15 10:30:00\"; // not ISO, Instant.parse would also fail\nLocalDateTime dt = TemporalConversions.toLocalDateTime(raw, zoneId); // throws\n// after\nString iso = raw.replace(' ', 'T') + (raw.length() <= 10 ? \"T00:00:00\" : \"\");\nLocalDateTime dt = TemporalConversions.toLocalDateTime(iso, zoneId);","handlingStrategy":"type-guard","validationCode":"boolean isConvertibleToDateTime(Object v) {\n    if (v instanceof String) {\n        try { java.time.Instant.parse((String) v); return true; }\n        catch (Exception e) { return false; }\n    }\n    return v instanceof Long || v instanceof java.util.Date\n        || v instanceof java.sql.Timestamp || v instanceof LocalDateTime;\n}","typeGuard":"boolean isIsoInstantString(Object v) {\n    return v instanceof String\n        && ((String) v).matches(\"\\\\d{4}-\\\\d{2}-\\\\d{2}T.*Z?.*\");\n}","tryCatchPattern":"try {\n    LocalDateTime dt = TemporalConversions.toLocalDateTime(value, zoneId);\n} catch (IllegalArgumentException e) {\n    LOG.warn(\"Unconvertible TIMESTAMP value {} ({}), using null\", value,\n        value == null ? \"null\" : value.getClass().getName());\n    return null;\n}","preventionTips":["Ensure string timestamps are ISO-8601 (Instant.parse-compatible) before calling","Use the correct toLocalDateTime overload for micros vs millis epoch values","Configure Debezium converters for TIMESTAMP columns (io.debezium.converters.TimestampConverter)","Record serverTimeZone consistently across reader and writer to avoid mixed representations"],"tags":["java","cdc","timestamp-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"}