apache/beam · error · UnsupportedOperationException

Unsupported Timestamp precision: {precision}

Error message

Unsupported Timestamp precision: {precision}

What it means

IcebergUtils.beamFieldTypeToIcebergFieldType maps a Beam Timestamp logical type to Iceberg's TimestampType.withZone() only when its precision argument equals Timestamp.MICROS. Any other precision (e.g. millis) is rejected with UnsupportedOperationException. Iceberg write conversion accepts only microsecond-precision timestamps with zone.

Source

Thrown at sdks/java/io/iceberg/src/main/java/org/apache/beam/sdk/io/iceberg/IcebergUtils.java:232

      Schema.LogicalType<?, ?> logicalType = checkArgumentNotNull(beamType.getLogicalType());
      if (logicalType instanceof FixedPrecisionNumeric) {
        Row args = Preconditions.checkArgumentNotNull(logicalType.getArgument());
        Integer precision = Preconditions.checkArgumentNotNull(args.getInt32("precision"));
        Integer scale = Preconditions.checkArgumentNotNull(args.getInt32("scale"));
        return new TypeAndMaxId(--nestedFieldId, Types.DecimalType.of(precision, scale));
      }
      if (logicalType instanceof PassThroughLogicalType) {
        return beamFieldTypeToIcebergFieldType(logicalType.getBaseType(), nestedFieldId);
      }
      String logicalTypeIdentifier = logicalType.getIdentifier();
      @Nullable Type type = BEAM_LOGICAL_TYPES_TO_ICEBERG_TYPES.get(logicalTypeIdentifier);
      if (type == null) {
        if (beamType.isLogicalType(Timestamp.IDENTIFIER)) {
          int precision = checkStateNotNull(logicalType.getArgument());
          if (precision == Timestamp.MICROS.getArgument()) {
            type = Types.TimestampType.withZone();
          } else {
            throw new UnsupportedOperationException(
                "Unsupported Timestamp precision: " + precision);
          }
        } else {
          throw new RuntimeException("Unsupported Beam logical type " + logicalTypeIdentifier);
        }
      }
      return new TypeAndMaxId(--nestedFieldId, type);
    } else if (beamType.getTypeName().isCollectionType()) { // ARRAY or ITERABLE
      Schema.FieldType beamCollectionType =
          Preconditions.checkArgumentNotNull(beamType.getCollectionElementType());

      // nestedFieldId is reserved for the list's collection type.
      // we increment here because further nested fields should use unique ID's
      TypeAndMaxId listInfo =
          beamFieldTypeToIcebergFieldType(beamCollectionType, nestedFieldId + 1);
      Type icebergCollectionType = listInfo.type;

      boolean elementTypeIsNullable =

View on GitHub (pinned to 12126d8942)

Solutions

  1. Convert the field to microsecond precision (Timestamp.of(..., MICROS)) before writing.
  2. Map the value to a supported type such as DateTime with micros precision in the Beam schema.
  3. Preprocess the Row to convert timestamps to Instant/micros-backed fields.
  4. If millisecond precision must be preserved, store the value as a LONG epoch field instead.

Example fix

// before
Schema.Field.of("ts", Schema.FieldType.logicalType(Timestamp.of(Timestamp.MILLIS)));

// after
Schema.Field.of("ts", Schema.FieldType.logicalType(Timestamp.of(Timestamp.MICROS)));
Defensive patterns

Strategy: validation

Validate before calling

boolean ok = field.getType().isLogicalType(Timestamp.IDENTIFIER)
    && Timestamp.MICROS.getArgument().equals(field.getType().getLogicalType().getArgument());

Try / catch

try {
  IcebergUtils.beamRowToIcebergRecord(schema, row);
} catch (UnsupportedOperationException e) {
  LOG.error("Timestamp precision not supported: {}", e.getMessage());
}

Prevention

When it happens

Trigger: Writing a Beam schema whose field is a Timestamp logical type with precision != Timestamp.MICROS.getArgument() (e.g. Timestamp.MILLIS) into an Iceberg table — thrown at IcebergUtils.java:232, including nested/list/map element types.

Common situations: PCollections built from sources emitting millisecond timestamps; custom logical types with non-micro precision; converting Avro/other millis-based schemas to Iceberg writes.

Related errors


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