apache/beam · error · IllegalArgumentException
Local timestamp (micros) can only be used with an underlying
Error message
Local timestamp (micros) can only be used with an underlying long type
What it means
AvroConverters' LocalTimestampMicrosConversion converts between Avro 'local-timestamp-micros' logical types and java.time.LocalDateTime. During schema validation it asserts the underlying Avro primitive type is LONG, since local-timestamp-micros is a logical type over a long (microseconds since epoch). If the schema declares a different physical type (e.g. int, string, record), validation fails immediately with this IllegalArgumentException.
Source
Thrown at sdks/java/extensions/avro/src/main/java/org/apache/beam/sdk/extensions/avro/schemas/utils/AvroJavaTimeConversions.java:66
public void validate(Schema schema) {
super.validate(schema);
if (schema.getType() != Schema.Type.LONG) {
throw new IllegalArgumentException(
"Local timestamp (millis) can only be used with an underlying long type");
}
}
}
public static class LocalTimestampMicros extends LogicalType {
private LocalTimestampMicros() {
super(LOCAL_TIMESTAMP_MICROS);
}
@Override
public void validate(Schema schema) {
super.validate(schema);
if (schema.getType() != Schema.Type.LONG) {
throw new IllegalArgumentException(
"Local timestamp (micros) can only be used with an underlying long type");
}
}
}
public static class DateConversion extends Conversion<LocalDate> {
@Override
public Class<LocalDate> getConvertedType() {
return LocalDate.class;
}
@Override
public String getLogicalTypeName() {
return "date";
}
@OverrideView on GitHub (pinned to 12126d8942)
Solutions
- Change the Avro field's underlying type to long (e.g. {"type":"long","logicalType":"local-timestamp-micros"}).
- If millisecond precision suffices and the type is int, use the local-timestamp-millis logical type with its matching conversion instead.
- If the field is not really a timestamp, drop the logicalType so the conversion is not applied.
- Regenerate/update Java Avro classes or the schema string so the declared type matches the conversion.
Example fix
// before (AVSC)
{"name":"eventTime","type":"int","logicalType":"local-timestamp-micros"}
// after
{"name":"eventTime","type":"long","logicalType":"local-timestamp-micros"} Defensive patterns
Strategy: validation
Validate before calling
if (schema.getType() != org.apache.avro.Schema.Type.LONG) {
throw new IllegalArgumentException("field " + schema.getName() + " must be long for local-timestamp-micros");
}
conversion.validate(schema); // safe
Type guard
boolean isLocalTsMicrosCompatible(org.apache.avro.Schema s) { return s.getType() == org.apache.avro.Schema.Type.LONG && "local-timestamp-micros".equals(s.getLogicalType() == null ? null : s.getLogicalType().getName()); } Try / catch
try {
conversion.validate(schema);
} catch (IllegalArgumentException e) {
throw new SchemaValidationException("Fix underlying Avro type to long: " + schema, e);
} Prevention
- Always define timestamp logical types over "long" in AVSC, never "int" or "string".
- Validate schemas at build/startup time rather than at record-processing time.
- Use Avro code generation from AVSC instead of hand-editing schema JSON.
- Pin Avro library versions across producer and consumer.
When it happens
Trigger: Calling Conversion.validate(schema) (directly or via Avro schema/Beam schema round-trip in AvroUtils) with a Schema whose getType() != Schema.Type.LONG while this conversion is registered for the local-timestamp-micros logical type.
Common situations: Hand-written Avro JSON/AVSC schemas where the field was declared as "int" or "string" instead of "long" with logicalType local-timestamp-micros; schema registry entries edited manually; older Avro versions or other producers writing timestamps as milliseconds-int that Beam consumers validate as micros-long.
Understand the failure class
Background: Schema validation failed / invalid input schema: payload rejected because its shape doesn't match the expected schema — this error's family across 28 libraries.
Related errors
- Unknown logical type " + identifier
- Could not infer Beam schema from Avro schema: {avroSchema}
- Could not infer Beam schema for class: {clazz}
- Unable to generate coder for schema {schema}
- Expecting exactly one field, found
AI-assisted analysis of apache/beam@12126d8942 (2026-09-13).
Data as JSON: /api/errors/9bd0bf94fac650de.
Report an issue: GitHub.