apache/beam · error · IllegalArgumentException
Unsupported precision for Timestamp logical type
Error message
Unsupported precision for Timestamp logical type
What it means
toTableFieldSchema throws this IllegalArgumentException when converting a Beam Schema field whose logical type is the Timestamp logical type but whose precision argument is not 9 (nanoseconds). The converter only supports mapping Beam Timestamp logical types with nanosecond precision to a BigQuery TIMESTAMP column with 12-digit (pico) precision; any other precision (millis, micros, etc.) is rejected.
Source
Thrown at sdks/java/io/google-cloud-platform/src/main/java/org/apache/beam/sdk/io/gcp/bigquery/BigQueryUtils.java:591
field.setFields(toTableFieldSchema(subType));
}
if (TypeName.MAP == type.getTypeName()) {
FieldType mapKeyType = Preconditions.checkArgumentNotNull(type.getMapKeyType());
FieldType mapValueType = Preconditions.checkArgumentNotNull(type.getMapValueType());
Schema mapSchema =
Schema.builder()
.addField(BIGQUERY_MAP_KEY_FIELD_NAME, mapKeyType)
.addField(BIGQUERY_MAP_VALUE_FIELD_NAME, mapValueType)
.build();
type = FieldType.row(mapSchema);
field.setFields(toTableFieldSchema(mapSchema));
field.setMode(Mode.REPEATED.toString());
}
Schema.LogicalType<?, ?> logicalType = type.getLogicalType();
if (logicalType != null && Timestamp.IDENTIFIER.equals(logicalType.getIdentifier())) {
int precision = Preconditions.checkArgumentNotNull(logicalType.getArgument());
if (precision != 9) {
throw new IllegalArgumentException(
"Unsupported precision for Timestamp logical type " + precision);
}
field.setType(StandardSQLTypeName.TIMESTAMP.toString()).setTimestampPrecision(12L);
} else {
field.setType(toStandardSQLTypeName(type).toString());
}
fields.add(field);
}
return fields;
}
/** Convert a Beam {@link Schema} to a BigQuery {@link TableSchema}. */
public static TableSchema toTableSchema(Schema schema) {
return new TableSchema().setFields(toTableFieldSchema(schema));
}
/** Convert a BigQuery {@link TableSchema} to a Beam {@link Schema}. */View on GitHub (pinned to 12126d8942)
Solutions
- Use the nanosecond Timestamp logical type: FieldType.logicalType(Timestamp.NANOS) for the affected field before writing to BigQuery.
- Alternatively change the field to FieldType.DATETIME (micros) which maps to a plain BigQuery TIMESTAMP without the precision path.
- Transform the schema/rows with Schema.toBuilder()/Row conversions to convert logical type precision (e.g. beam convertTimestamps) prior to the sink.
Example fix
// before
Field f = Field.of("ts", FieldType.logicalType(Timestamp.MICROS));
// after
Field f = Field.of("ts", FieldType.logicalType(Timestamp.NANOS)); Defensive patterns
Strategy: validation
Validate before calling
static void assertTimestampPrecisionsAreNanos(Schema schema) {
for (Field f : schema.getFields()) {
Schema.LogicalType<?, ?> lt = f.getType().getLogicalType();
if (lt != null && "Timestamp".equals(lt.getIdentifier())) {
Object arg = lt.getArgument();
if (arg instanceof Number && ((Number) arg).intValue() != 9) {
throw new IllegalArgumentException("Field " + f.getName() + " needs Timestamp.NANOS (precision 9) for BigQuery");
}
}
}
} Type guard
static boolean isBqCompatibleTimestamp(Field f) {
Schema.LogicalType<?, ?> lt = f.getType().getLogicalType();
return lt == null || !"Timestamp".equals(lt.getIdentifier())
|| (lt.getArgument() instanceof Number && ((Number) lt.getArgument()).intValue() == 9);
} Try / catch
try {
TableSchema ts = BigQueryUtils.toTableSchema(beamSchema);
} catch (IllegalArgumentException e) {
if (String.valueOf(e.getMessage()).startsWith("Unsupported precision for Timestamp")) {
Schema fixed = rebuildWithNanosTimestamps(beamSchema);
TableSchema ts = BigQueryUtils.toTableSchema(fixed);
} else { throw e; }
} Prevention
- Standardize on Timestamp.NANOS logical types for fields destined for BigQuery TIMESTAMP columns.
- When sharing schemas across sinks (Parquet/Avro/BigQuery), normalize timestamp logical types per sink before conversion.
- Add a unit test converting your production schema through BigQueryUtils.toTableSchema to catch precision regressions.
When it happens
Trigger: Calling BigQueryUtils.toTableSchema / BigQueryIO.writeTableRows-ish schema writes with a Beam Schema field typed FieldType.logicalType(Timestamp.MILLIS) (argument 3), Timestamp.MICROS (6), or any Timestamp logical type whose getArgument() is not 9.
Common situations: Schemas built with Timestamp.MICROS/MILLIS for readability, then written to BigQuery where only nanosecond-precision Timestamp logical types are accepted by this converter; sharing a schema across sinks (Parquet accepts micros, BigQuery does not).
Understand the failure class
Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.
Related errors
- Unhandled logical type ${identifier}
- Converting BigQuery type to Beam type is unsupported
- Array of collection is not supported in BigQuery.
- Unknown logical type
- Unknown logical type " + identifier
AI-assisted analysis of apache/beam@12126d8942 (2026-09-13).
Data as JSON: /api/errors/0f5a3e64e2ddb3f7.
Report an issue: GitHub.