apache/seatunnel · error · java.lang.IllegalArgumentException
Unable to convert to LocalDateTime from unexpected value ''
Error message
Unable to convert to LocalDateTime from unexpected value '' of type
What it means
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.
Source
Thrown at seatunnel-connectors-v2/connector-cdc/connector-cdc-base/src/main/java/org/apache/seatunnel/connectors/cdc/debezium/utils/TemporalConversions.java:222
millis = MILLISECONDS_PER_SECOND + millis;
}
int nanosOfSecond = (int) (millis * NANOSECONDS_PER_MILLISECOND);
return LocalDateTime.of(
date.getYear() + 1900,
date.getMonth() + 1,
date.getDate(),
date.getHours(),
date.getMinutes(),
date.getSeconds(),
nanosOfSecond);
}
if (obj instanceof String) {
String str = (String) obj;
// TIMESTAMP type is encoded in string type
Instant instant = Instant.parse(str);
return LocalDateTime.ofInstant(instant, serverTimeZone);
}
throw new IllegalArgumentException(
"Unable to convert to LocalDateTime from unexpected value '"
+ obj
+ "' of type "
+ obj.getClass().getName());
}
}
View on GitHub (pinned to cf67b549a7)
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
Example fix
// before
String raw = "2024-01-15 10:30:00"; // not ISO, Instant.parse would also fail
LocalDateTime dt = TemporalConversions.toLocalDateTime(raw, zoneId); // throws
// after
String iso = raw.replace(' ', 'T') + (raw.length() <= 10 ? "T00:00:00" : "");
LocalDateTime dt = TemporalConversions.toLocalDateTime(iso, zoneId); Defensive patterns
Strategy: type-guard
Validate before calling
boolean isConvertibleToDateTime(Object v) {
if (v instanceof String) {
try { java.time.Instant.parse((String) v); return true; }
catch (Exception e) { return false; }
}
return v instanceof Long || v instanceof java.util.Date
|| v instanceof java.sql.Timestamp || v instanceof LocalDateTime;
} Type guard
boolean isIsoInstantString(Object v) {
return v instanceof String
&& ((String) v).matches("\\d{4}-\\d{2}-\\d{2}T.*Z?.*");
} Try / catch
try {
LocalDateTime dt = TemporalConversions.toLocalDateTime(value, zoneId);
} catch (IllegalArgumentException e) {
LOG.warn("Unconvertible TIMESTAMP value {} ({}), using null", value,
value == null ? "null" : value.getClass().getName());
return null;
} Prevention
- 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
When it happens
Trigger: 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.
Common situations: 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.
Understand the failure class
Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.
Related errors
- Unable to convert to LocalDate from unexpected value '' of t
- Unable to convert to LocalDate from a java.sql.Date value '
- Sparse vector value must be a Number, but got: %s
- Unsupported timestamp type:
- Value is not a BSON date or timestamp
AI-assisted analysis of apache/seatunnel@cf67b549a7 (2026-09-10).
Data as JSON: /api/errors/3e627faaead1b505.
Report an issue: GitHub.