apache/beam · error · RuntimeException

Unsupported precision for Timestamp logical type " + precisi

Error message

Unsupported precision for Timestamp logical type " + precision

What it means

BeamRowToStorageApiProto converts a Beam Schema/Row into a BigQuery Storage API TableSchema/protobuf message. The Beam Timestamp logical type carries a precision argument; this converter only supports nanosecond precision (9 fractional digits, Timestamp.NANOS). Any other precision is rejected because BigQuery's storage-write mapping here only defines behavior for that case.

Source

Thrown at sdks/java/io/google-cloud-platform/src/main/java/org/apache/beam/sdk/io/gcp/bigquery/BeamRowToStorageApiProto.java:258

        if (elementFieldSchema.hasTimestampPrecision()) {
          builder = builder.setTimestampPrecision(elementFieldSchema.getTimestampPrecision());
        }
        builder.addAllFields(elementFieldSchema.getFieldsList());
        builder = builder.setMode(TableFieldSchema.Mode.REPEATED);
        break;
      case LOGICAL_TYPE:
        @Nullable LogicalType<?, ?> logicalType = field.getType().getLogicalType();
        if (logicalType == null) {
          throw new RuntimeException("Unexpected null logical type " + field.getType());
        }
        @Nullable TableFieldSchema.Type type;
        if (logicalType.getIdentifier().equals(Timestamp.IDENTIFIER)) {
          int precision =
              Preconditions.checkNotNull(
                  logicalType.getArgument(),
                  "Expected logical type argument for timestamp precision.");
          if (precision != 9) {
            throw new RuntimeException(
                "Unsupported precision for Timestamp logical type " + precision);
          }
          // Map Timestamp.NANOS logical type to BigQuery TIMESTAMP(12) for nanosecond precision
          type = TableFieldSchema.Type.TIMESTAMP;
          builder.setTimestampPrecision(Int64Value.newBuilder().setValue(12L).build());
        } else {
          type = LOGICAL_TYPES.get(logicalType.getIdentifier());
          if (type == null) {
            throw new RuntimeException("Unsupported logical type " + field.getType());
          }
        }
        builder = builder.setType(type);
        break;
      case MAP:
        @Nullable FieldType keyType = field.getType().getMapKeyType();
        @Nullable FieldType valueType = field.getType().getMapValueType();
        if (keyType == null) {
          throw new RuntimeException(

View on GitHub (pinned to 12126d8942)

Solutions

  1. Use the nanosecond Timestamp logical type: FieldType.logicalType(Timestamp.of(TimeUnit.NANOSECONDS)) (precision 9).
  2. If micro/milli precision suffices, use a plain DATETIME/datetime type or a non-logical type instead of the Timestamp logical type.
  3. If you own the pipeline, catch/translate the RuntimeException at schema-construction time and fall back to a supported field type.
  4. Check the Beam version: newer releases may support more precisions; upgrade sdks/java/io/google-cloud-platform.

Example fix

// before
FieldType ts = FieldType.logicalType(Timestamp.of(TimeUnit.MICROSECONDS));
// after
FieldType ts = FieldType.logicalType(Timestamp.of(TimeUnit.NANOSECONDS));
Defensive patterns

Strategy: validation

Validate before calling

for (Schema.Field f : schema.getFields()) {
  if (f.getType().getTypeName() == Schema.TypeName.LOGICAL_TYPE) {
    LogicalType<?, ?> lt = f.getType().getLogicalType();
    if (lt != null && lt.getIdentifier().equals(Timestamp.IDENTIFIER)
        && !Integer.valueOf(9).equals((Integer) lt.getArgument())) {
      throw new IllegalArgumentException("Field " + f.getName() + " must use Timestamp NANOS precision (9)");
    }
  }
}

Type guard

boolean isSupportedTimestamp(Schema.FieldType t) {
  return t.getTypeName() != Schema.TypeName.LOGICAL_TYPE
      || !(t.getLogicalType() instanceof Timestamp)
      || ((Integer) t.getLogicalType().getArgument()) == 9;
}

Try / catch

try {
  TableSchema ts = BeamRowToStorageApiProto.protoTableSchemaFromBeamSchema(schema);
} catch (RuntimeException e) {
  if (e.getMessage().startsWith("Unsupported precision for Timestamp")) {
    schema = normalizeTimestampPrecision(schema); // rewrite fields to NANOS
  } else { throw e; }
}

Prevention

When it happens

Trigger: Building a TableSchema via BeamRowToStorageApiProto.protoTableSchemaFromBeamSchema (or elementFieldSchema) for a Beam schema whose field is a Timestamp logical type with an argument other than 9, e.g. Timestamp.of(TimeUnit.MICROSECONDS) or custom precision.

Common situations: Users declaring a schema field with FieldType.logicalType(Timestamp.of(TimeUnit.MICROSECONDS)) or the default microsecond-precision timestamp, then writing to BigQuery via the Storage Write API sink.

Related errors


AI-assisted analysis of apache/beam@12126d8942 (2026-09-13). Data as JSON: /api/errors/6becfa3d99a69ce4. Report an issue: GitHub.