apache/beam · error · UnsupportedOperationException

Unsupported Iceberg type for Beam type DATETIME: {valueClass

Error message

Unsupported Iceberg type for Beam type DATETIME: {valueClass}

What it means

getBeamDateTimeValue converts an Iceberg value into a Beam joda DateTime for DATETIME columns. It accepts Iceberg LocalDateTime, Long (micros), and String; any other runtime type throws UnsupportedOperationException, indicating the Iceberg value's class is not a recognized datetime representation.

Source

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

        break;
      default:
        throw new UnsupportedOperationException(
            "Unsupported Beam type: " + field.getType().getTypeName());
    }
  }

  private static DateTime getBeamDateTimeValue(Object icebergValue) {
    long micros;
    if (icebergValue instanceof OffsetDateTime) {
      micros = DateTimeUtil.microsFromTimestamptz((OffsetDateTime) icebergValue);
    } else if (icebergValue instanceof LocalDateTime) {
      micros = DateTimeUtil.microsFromTimestamp((LocalDateTime) icebergValue);
    } else if (icebergValue instanceof Long) {
      micros = (long) icebergValue;
    } else if (icebergValue instanceof String) {
      return DateTime.parse((String) icebergValue);
    } else {
      throw new UnsupportedOperationException(
          "Unsupported Iceberg type for Beam type DATETIME: " + icebergValue.getClass());
    }
    return new DateTime(micros / 1000L);
  }

  private static Object getLogicalTypeValue(Object icebergValue, Schema.FieldType type) {
    if (icebergValue instanceof String) {
      String strValue = (String) icebergValue;
      if (type.isLogicalType(SqlTypes.DATE.getIdentifier())) {
        return LocalDate.parse(strValue);
      } else if (type.isLogicalType(SqlTypes.TIME.getIdentifier())) {
        return LocalTime.parse(strValue);
      } else if (type.isLogicalType(SqlTypes.DATETIME.getIdentifier())) {
        return LocalDateTime.parse(strValue);
      } else if (type.isLogicalType(Timestamp.IDENTIFIER)) {
        return OffsetDateTime.parse(strValue).toInstant();
      }
    } else if (icebergValue instanceof Long) {

View on GitHub (pinned to 12126d8942)

Solutions

  1. Map timestamptz columns to a Beam field whose value conversion accepts OffsetDateTime, or pre-convert: OffsetDateTime -> LocalDateTime via toLocalDateTime()/toInstant().toEpochMilli()*1000
  2. If you get a java.sql.Timestamp or java.util.Date, convert first: Timestamp.toLocalDateTime() or date.getTime()*1000 for micros
  3. Verify which Iceberg runtime/reader produced the value and normalize at ingestion
  4. Wrap conversion with a small adapter function that normalizes known classes to the accepted three before calling the IO

Example fix

// before
Object v = offsetDateTimeValue; // java.time.OffsetDateTime
// after
Object v = offsetDateTimeValue.toInstant().toEpochMilli() * 1000L; // micros Long
Defensive patterns

Strategy: type-guard

Validate before calling

if (!(v instanceof java.time.LocalDateTime) && !(v instanceof Long) && !(v instanceof String)) {
  throw new IllegalArgumentException("DATETIME field value must be LocalDateTime/Long/String, got " + v.getClass());
}

Type guard

boolean isBeamDatetimeCompatible(Object v) {
  return v instanceof java.time.LocalDateTime || v instanceof Long || v instanceof String;
}

Try / catch

try {
  row = structToRow(schema, struct);
} catch (UnsupportedOperationException e) {
  if (e.getMessage().startsWith("Unsupported Iceberg type for Beam type DATETIME")) {
    // convert OffsetDateTime/Date to micros and retry
  } else { throw e; }
}

Prevention

When it happens

Trigger: structToRow/addIcebergValue converts a DATETIME Beam field whose Iceberg value is not LocalDateTime, Long, or String — e.g. java.time.OffsetDateTime from a timestamptz column mapped onto a DATETIME field, an Iceberg Timestamp value object, or a BigDecimal/byte[] from a custom deserializer.

Common situations: Mapping a timestamptz Iceberg column to a non-nullable DATETIME Beam field where the reader returned OffsetDateTime; custom Iceberg object models returning different classes; mixing read paths (avro-based vs internal) with different representations.

Understand the failure class

Background: Type mismatch errors: IllegalArgumentException, TypeError and type guards across 150 open-source libraries — this error's family across 150 libraries.

Related errors


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