apache/beam · error · UnsupportedOperationException

Unsupported row type: {valueClass}

Error message

Unsupported row type: {valueClass}

What it means

In addIcebergValue, Beam Row-typed fields must hold either an org.apache.hadoop.hive.ql.exec.Record-style org.apache.avro.generic.Record-like Record or a StructLike; any other object in a Row-type field is rejected with UnsupportedOperationException, since the nested Beam Row cannot be constructed from it.

Source

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

        break;
      case BYTES:
        // Beam uses byte[]. Iceberg represents `binary` as a ByteBuffer but `fixed` as a byte[].
        rowBuilder.addValue(
            icebergValue instanceof byte[]
                ? (byte[]) icebergValue
                : ((ByteBuffer) icebergValue).array());
        break;
      case ROW:
        Schema nestedSchema =
            checkArgumentNotNull(
                field.getType().getRowSchema(),
                "Corrupted schema: Row type did not have associated nested schema.");
        if (icebergValue instanceof Record) {
          rowBuilder.addValue(icebergRecordToBeamRow(nestedSchema, (Record) icebergValue));
        } else if (icebergValue instanceof StructLike) {
          rowBuilder.addValue(structToRow(nestedSchema, (StructLike) icebergValue));
        } else {
          throw new UnsupportedOperationException(
              "Unsupported row type: " + icebergValue.getClass());
        }
        break;
      case LOGICAL_TYPE:
        rowBuilder.addValue(getLogicalTypeValue(icebergValue, field.getType()));
        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);

View on GitHub (pinned to 12126d8942)

Solutions

  1. Ensure nested struct values implement org.apache.iceberg.types.Types.StructType-compatible StructLike (use iceberg's GenericData.Record or copy via the table's struct projection)
  2. Convert Maps manually: build a Record from the map keys following the nested schema before adding it to the row
  3. Check for version mismatches between the Iceberg runtime used to write and read records
  4. If you control the source, wrap the value: GenericData.Record rec = new GenericData.Record(nestedSchema.asStruct()); copy fields; then convert

Example fix

// before
rowBuilder.addValue(someJavaMapForStructField);
// after
Record rec = GenericRecordUtil.recordFromMap(nestedSchema.asStruct(), someJavaMapForStructField);
rowBuilder.addValue(icebergRecordToBeamRow(nestedSchema, rec));
Defensive patterns

Strategy: type-guard

Validate before calling

Object nested = record.getField(i);
if (!(nested instanceof org.apache.iceberg.data.Record) && !(nested instanceof StructLike)) {
  throw new IllegalArgumentException("Nested struct field must be Record/StructLike, got " + nested.getClass());
}

Type guard

boolean isStructLike(Object v) {
  return v instanceof org.apache.iceberg.data.Record || v instanceof StructLike;
}

Try / catch

try {
  row = structToRow(schema, struct);
} catch (UnsupportedOperationException e) {
  if (e.getMessage().startsWith("Unsupported row type")) {
    // wrap value into a Record before retrying
  } else { throw e; }
}

Prevention

When it happens

Trigger: A nested Iceberg struct field's value is neither a Record nor a StructLike — e.g. the value is a java.util.Map, a List, a generic Object produced by a custom deserializer, or the Iceberg record implementation returns raw containers for struct columns.

Common situations: Custom record readers/writers populating struct fields with Maps instead of Iceberg Record/StructLike; third-party libraries returning wrapped values; mixing Iceberg runtime versions where the record implementation changed class.

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/93445c793d0795e6. Report an issue: GitHub.