apache/beam · error · IllegalArgumentException
DateTime64 requires a Joda ReadableInstant or…
Error message
DateTime64 requires a Joda ReadableInstant or java.time.Instant, got
What it means
Thrown by ClickHouseWriter.encodeDateTime64 when the value for a DateTime64 column is neither a java.time.Instant nor a Joda ReadableInstant. DateTime64 encoding needs an instant-like type to compute epoch seconds and sub-second nanos; other types (String, Long, java.util.Date, null) are rejected explicitly, with 'null' reported by name.
Solutions
- Convert to java.time.Instant before writing (Instant.parse(...), Instant.ofEpochMilli(millis), date.toInstant()).
- Joda DateTime (ReadableInstant) values are also accepted directly.
- Parse string timestamps with the correct DateTimeFormatter and zone upstream of the write.
- Populate the Row field so nulls never reach the writer.
Example fix
// before
writer.writeValue("2024-01-01 00:00:00"); // String rejected
// after
java.time.Instant instant = java.time.Instant.parse("2024-01-01T00:00:00Z");
writer.writeValue(instant); Defensive patterns
Strategy: type-guard
Validate before calling
import java.time.Instant;
import org.joda.time.ReadableInstant;
boolean isDateTime64Compatible(Object v) {
return v instanceof Instant || v instanceof ReadableInstant;
} Type guard
java.time.Instant asInstant(Object v) {
if (v instanceof java.time.Instant) return (java.time.Instant) v;
if (v instanceof org.joda.time.ReadableInstant) return java.time.Instant.ofEpochMilli(((org.joda.time.ReadableInstant) v).getMillis());
if (v instanceof Long) return java.time.Instant.ofEpochMilli((Long) v);
if (v instanceof String) return java.time.Instant.parse((String) v);
throw new IllegalArgumentException("Not convertible to Instant: " + v);
} Try / catch
try {
writer.encodeDateTime64(value, precision);
} catch (IllegalArgumentException e) {
if (e.getMessage() != null && e.getMessage().contains("DateTime64 requires")) {
throw new SchemaMappingException("Row field must be Instant or ReadableInstant for DateTime64 column");
}
throw e;
} Prevention
- Define Beam Row schemas with Instant fields for DateTime64 columns.
- Parse timestamp strings once at source ingestion, not at write time.
- Convert java.util.Date via date.toInstant() and epoch millis via Instant.ofEpochMilli().
- Handle nulls explicitly upstream so nulls never reach the writer.
When it happens
Trigger: Calling writeValue on a DateTime64 column with a String timestamp, epoch-millis Long, java.util.Date, or null instead of Instant/ReadableInstant.
Common situations: Rows built from JSON/CSV sources where timestamps remain strings; passing System.currentTimeMillis() directly; legacy code carrying java.util.Date; missing fields leaving nulls in the Row.
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
- Unsupported Beam type for Iceberg timestamp with timezone
- Unsupported Iceberg type for Beam type DATETIME
- bad type: , want
- Can't convert 'string' map keys to
- Cannot merge two types: +fieldType1.getTypeName()+ and…
AI-assisted analysis of apache/beam@12126d8942 (2026-09-13).
Data as JSON: /api/errors/40ab86a6a72e30f7.
Report an issue: GitHub.
Appendix: source
Thrown at sdks/java/io/clickhouse/src/main/java/org/apache/beam/sdk/io/clickhouse/ClickHouseWriter.java:101
* 64-bit integer counting ticks of size 10<sup>-precision</sup> seconds since the Unix epoch.
*
* <p>Accepts either a Joda {@link ReadableInstant} (millisecond precision) or a {@link
* java.time.Instant} (nanosecond precision). Sub-tick fractions are truncated toward negative
* infinity, matching ClickHouse's own encoding for negative timestamps.
*/
static long encodeDateTime64(Object value, int precision) {
long epochSecond;
int nanoOfSecond;
if (value instanceof java.time.Instant) {
java.time.Instant inst = (java.time.Instant) value;
epochSecond = inst.getEpochSecond();
nanoOfSecond = inst.getNano();
} else if (value instanceof ReadableInstant) {
long millis = ((ReadableInstant) value).getMillis();
epochSecond = Math.floorDiv(millis, 1000L);
nanoOfSecond = (int) Math.floorMod(millis, 1000L) * 1_000_000;
} else {
throw new IllegalArgumentException(
"DateTime64 requires a Joda ReadableInstant or java.time.Instant, got "
+ (value == null ? "null" : value.getClass().getName()));
}
long subSecondTicks = nanoOfSecond / POW10[9 - precision];
return Math.addExact(Math.multiplyExact(epochSecond, POW10[precision]), subSecondTicks);
}
@SuppressWarnings("unchecked")
static void writeNullableValue(ClickHouseOutputStream stream, ColumnType columnType, Object value)
throws IOException {
if (value == null) {
BinaryStreamUtils.writeNull(stream);
} else {
BinaryStreamUtils.writeNonNull(stream);
writeValue(stream, columnType, value);
}
}View on GitHub (pinned to 12126d8942)