apache/seatunnel · error · RuntimeException
Cannot convert timestamptz: , type:
Error message
Cannot convert timestamptz: , type:
What it means
Iceberg RowConverter throws this RuntimeException when a timestamptz (Iceberg TimestampType with adjustToUTC) value cannot be converted to OffsetDateTime. convertOffsetDateTime accepts String (parsed), LocalDateTime, OffsetDateTime, and Date; anything else is rejected with both value and class in the message.
Solutions
- Convert the value to OffsetDateTime or java.util.Date before the sink.
- Add a transform CAST(column, TIMESTAMP) so SeaTunnel delivers a supported temporal type.
- If holding epoch millis, convert: Instant.ofEpochMilli(ms).atOffset(ZoneOffset.UTC).
- Check source connector timestamp mapping config so timestamps arrive as SeaTunnel TimestampType.
Example fix
// before writer.write(idx, 1710000000000L); // Long not accepted // after writer.write(idx, Instant.ofEpochMilli(1710000000000L).atOffset(ZoneOffset.UTC)); // OffsetDateTime accepted
Defensive patterns
Strategy: type-guard
Validate before calling
if (!(v instanceof OffsetDateTime) && !(v instanceof LocalDateTime) && !(v instanceof java.util.Date) && !(v instanceof String)) throw new IllegalArgumentException("timestamptz column must be OffsetDateTime/LocalDateTime/Date/String, got " + (v == null ? "null" : v.getClass().getName())); Type guard
boolean isTimestamptzConvertible(Object v) { return v instanceof OffsetDateTime || v instanceof LocalDateTime || v instanceof java.util.Date || v instanceof String; } Try / catch
try { sink.write(row); } catch (RuntimeException e) { if (e.getMessage() != null && e.getMessage().startsWith("Cannot convert timestamptz")) { /* convert epoch/Instant to OffsetDateTime or DLQ */ } else throw e; } Prevention
- Convert epoch millis/Instant to OffsetDateTime before the sink
- Map source timestamps to SeaTunnel TimestampType
- Verify timestamp column type is not a Long in the SeaTunnel catalog table
When it happens
Trigger: convertOffsetDateTime receives an unsupported object (e.g. Long epoch millis, ZonedDateTime, or a nested type) while converting a field for a timestamptz Iceberg column via convertTimestampValue.
Common situations: Sources emitting epoch millis as Long for timestamp columns; JDBC sources returning custom temporal types; CDC formats delivering timestamps in wrapper objects.
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
- Cannot convert timestamp: , type:
- Cannot convert date:
- Cannot convert time:
- Cannot convert to BigDecimal:
- Cannot convert to binary:
AI-assisted analysis of apache/seatunnel@cf67b549a7 (2026-09-10).
Data as JSON: /api/errors/74c9ff439d0e3ba6.
Report an issue: GitHub.
Appendix: source
Thrown at seatunnel-connectors-v2/connector-iceberg/src/main/java/org/apache/seatunnel/connectors/seatunnel/iceberg/data/RowConverter.java:441
private OffsetDateTime convertOffsetDateTime(Object value) {
if (value instanceof Number) {
long millis = ((Number) value).longValue();
return DateTimeUtil.timestamptzFromMicros(millis * 1000);
} else if (value instanceof String) {
return parseOffsetDateTime((String) value);
} else if (value instanceof OffsetDateTime) {
return (OffsetDateTime) value;
} else if (value instanceof LocalDateTime) {
// Convert to OffsetDateTime using the system(jvm) default timezone
return ((LocalDateTime) value)
.atZone(ZoneId.systemDefault())
.withZoneSameInstant(ZoneOffset.UTC)
.toOffsetDateTime();
} else if (value instanceof Date) {
return DateTimeUtil.timestamptzFromMicros(((Date) value).getTime() * 1000);
}
throw new RuntimeException(
"Cannot convert timestamptz: " + value + ", type: " + value.getClass());
}
private OffsetDateTime parseOffsetDateTime(String str) {
String tsStr = ensureTimestampFormat(str);
try {
return OFFSET_TS_FMT.parse(tsStr, OffsetDateTime::from);
} catch (DateTimeParseException e) {
return LocalDateTime.parse(tsStr, DateTimeFormatter.ISO_LOCAL_DATE_TIME)
.atOffset(ZoneOffset.UTC);
}
}
private LocalDateTime convertLocalDateTime(Object value) {
if (value instanceof Number) {
long millis = ((Number) value).longValue();
return DateTimeUtil.timestampFromMicros(millis * 1000);
} else if (value instanceof String) {View on GitHub (pinned to cf67b549a7)