apache/beam · error · AssertionError
micros_instant logical type encountered a Java Instant with
Error message
micros_instant logical type encountered a Java Instant with greater than microsecond precision.
What it means
The micros_instant logical type represents instants with only microsecond precision. toBaseType throws an AssertionError if the java.time.Instant has sub-microsecond nanos (nano % 1000 != 0), since precision would be lost.
Source
Thrown at sdks/java/core/src/main/java/org/apache/beam/sdk/schemas/logicaltypes/MicrosInstant.java:56
* NanosInstant}.
*/
public class MicrosInstant implements Schema.LogicalType<Instant, Row> {
public static final String IDENTIFIER =
SchemaApi.LogicalTypes.Enum.MICROS_INSTANT
.getValueDescriptor()
.getOptions()
.getExtension(RunnerApi.beamUrn);
// TODO(https://github.com/apache/beam/issues/20540): This should be a constant
private final Schema schema;
public MicrosInstant() {
this.schema = Schema.builder().addInt64Field("seconds").addInt32Field("micros").build();
}
@Override
public Row toBaseType(Instant input) {
if (input.getNano() % 1000 != 0) {
throw new AssertionError(
"micros_instant logical type encountered a Java "
+ "Instant with greater than microsecond precision.");
}
return Row.withSchema(schema).addValues(input.getEpochSecond(), input.getNano() / 1000).build();
}
@Override
public Instant toInputType(Row row) {
return Instant.ofEpochSecond(
checkArgumentNotNull(
row.getInt64(0), "While trying to convert to Instant: Row missing seconds field"),
checkArgumentNotNull(
row.getInt32(1), "While trying to convert to Instant: Row missing micros field")
* 1000);
}
@Override
public String getIdentifier() {View on GitHub (pinned to 12126d8942)
Solutions
- Truncate the Instant to microseconds before conversion: input.truncatedTo(ChronoUnit.MICROS).
- Normalize at the source (round/truncate timestamps when produced).
- If nanosecond precision is required, use a logical type that supports nanos instead of micros_instant.
Example fix
// before Row r = Row.withSchema(schema).addValues(Instant.now(), ...).build(); // after Instant t = Instant.now().truncatedTo(ChronoUnit.MICROS); Row r = Row.withSchema(schema).addValues(t, ...).build();
Defensive patterns
Strategy: validation
Validate before calling
// Java: truncate instants to microsecond precision before use Instant safe = input.truncatedTo(ChronoUnit.MICROS);
Type guard
// Java
public static boolean isMicrosPrecise(Instant t) { return t.getNano() % 1000 == 0; } Prevention
- Truncate all Instant.now() and external timestamps to ChronoUnit.MICROS.
- Never feed nanosecond-precision sources into micros_instant columns.
When it happens
Trigger: Converting an Instant created with nanosecond precision (e.g. Instant.now() on JVMs reporting finer clocks, or truncatedFrom with NANOS) through a schema using MicrosInstant.
Common situations: Passing Instant.now() values directly into rows on JDK 9+ where the clock can have nanosecond resolution.
Understand the failure class
Background: "value must be between 0 and 1" / "out of range" / "must not be negative" errors: fixing range-validation failures across open-source libraries — this error's family across 42 libraries.
Related errors
- Timestamp logical type precision not supported:${precision}
- BigQuery data contained value %s with sub-millisecond precis
- Unsupported Timestamp precision: {precision}
- beam:logical_type:timestamp:v1 requires a precision argument
- Extract file timestamp failed: got file timestamp == 0.
AI-assisted analysis of apache/beam@12126d8942 (2026-09-13).
Data as JSON: /api/errors/67746827bb5dc3d4.
Report an issue: GitHub.