apache/seatunnel · error · IllegalArgumentException
Unable to convert to LocalDateTime from unexpected value '${
Error message
Unable to convert to LocalDateTime from unexpected value '${value}' of type ${value.getClass().getName()} What it means
convertToTimestamp converts TIMESTAMP columns to LocalDateTime; its switch covers known input types and the default branch rejects any other class with an IllegalArgumentException naming the value and its class name.
Source
Thrown at seatunnel-connectors-v2/connector-cdc/connector-cdc-tidb/src/main/java/org/apache/seatunnel/connectors/seatunnel/cdc/tidb/source/converter/DefaultDataConverter.java:333
int nanoSecond = instant.getNano();
long millisecond = epochSecond * 1000L + (long) (nanoSecond / 1000000);
int nanoOfMillisecond = nanoSecond % 1000000;
return toLocalDateTime(millisecond, nanoOfMillisecond);
}
break;
case TypeDatetime:
if (value instanceof Timestamp) {
LocalDateTime dateTime = ((Timestamp) value).toLocalDateTime();
long epochDay = dateTime.toLocalDate().toEpochDay();
long nanoOfDay = dateTime.toLocalTime().toNanoOfDay();
long millisecond = epochDay * 86400000L + nanoOfDay / 1000000L;
int nanoOfMillisecond = (int) (nanoOfDay % 1000000L);
return toLocalDateTime(millisecond, nanoOfMillisecond);
}
break;
default:
throw new IllegalArgumentException(
"Unable to convert to LocalDateTime from unexpected value '"
+ value
+ "' of type "
+ value.getClass().getName());
}
return value;
}
public static LocalDateTime toLocalDateTime(long millisecond, int nanoOfMillisecond) {
// 86400000 = 24 * 60 * 60 * 1000
int date = (int) (millisecond / 86400000);
int time = (int) (millisecond % 86400000);
if (time < 0) {
--date;
time += 86400000;
}
long nanoOfDay = time * 1_000_000L + nanoOfMillisecond;
LocalDate localDate = LocalDate.ofEpochDay(date);View on GitHub (pinned to cf67b549a7)
Solutions
- Identify the actual runtime class from the message and add a conversion branch for it in convertToTimestamp
- Parse Strings with the expected TiDB datetime pattern into LocalDateTime explicitly
- Ensure schema types match the real TiDB column types so only temporal classes arrive
- Align SeaTunnel connector-cdc-tidb with the TiDB CDC version in use
Example fix
// before
default:
throw new IllegalArgumentException("Unable to convert to LocalDateTime...");
// after
case String:
return LocalDateTime.parse(((String) value).replace(' ', 'T'));
default:
throw new IllegalArgumentException("Unable to convert to LocalDateTime..."); Defensive patterns
Strategy: type-guard
Validate before calling
static boolean isLocalDateTimeConvertible(Object v) {
return v instanceof LocalDateTime || v instanceof java.sql.Timestamp
|| v instanceof Long || v instanceof String;
} Type guard
static LocalDateTime toLdtSafe(Object v) {
if (v instanceof LocalDateTime) return (LocalDateTime) v;
if (v instanceof java.sql.Timestamp) return ((java.sql.Timestamp) v).toLocalDateTime();
if (v instanceof Long) return Instant.ofEpochMilli((Long) v).atZone(ZoneId.systemDefault()).toLocalDateTime();
if (v instanceof String) return LocalDateTime.parse(((String) v).replace(' ', 'T'));
return null;
} Try / catch
try {
return convertToTimestamp(value, dataType);
} catch (IllegalArgumentException e) {
log.error("TIMESTAMP conversion failed for {} : {}", value.getClass(), e.getMessage());
throw e;
} Prevention
- Match SeaTunnel schema types to real TiDB column types
- Add a String branch if your TiDB CDC version emits datetime strings
- Run a sample snapshot test after connector upgrades to catch class changes early
When it happens
Trigger: A TIMESTAMP column whose runtime value is outside the handled types — e.g. String, byte[], or Integer epoch — falling into the switch's default branch during convert().
Common situations: TiDB CDC emitting TIMESTAMP as String after an upgrade; schema drift mapping a non-temporal column to TIMESTAMP; wrapper objects from upstream transforms.
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
- Unable to convert to decimal from unexpected value '${value}
- Unable to convert TIMESTAMP_TZ from String value: '${value}'
- Unsupported value type for TIMESTAMP_TZ conversion: ${value.
- Unable to parse OffsetDateTime from CDC TIMESTAMP_TZ value:
- not supported create new Offset by timestamp.
AI-assisted analysis of apache/seatunnel@cf67b549a7 (2026-09-10).
Data as JSON: /api/errors/b8cc9fadab033090.
Report an issue: GitHub.