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
- 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)
- Convert Maps manually: build a Record from the map keys following the nested schema before adding it to the row
- Check for version mismatches between the Iceberg runtime used to write and read records
- 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
- Use iceberg's GenericData.Record for nested structs
- Avoid Maps for struct columns in custom deserializers
- Pin one Iceberg runtime version across the pipeline
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
- Unsupported Beam type for Iceberg timestamp with timezone: {
- Unsupported Iceberg type for Beam type DATETIME: {valueClass
- Unexpected Beam type: {}
- Unable to provide coder for %s, this factory can only provid
- The input schema must have exactly one field of type byte.
AI-assisted analysis of apache/beam@12126d8942 (2026-09-13).
Data as JSON: /api/errors/93445c793d0795e6.
Report an issue: GitHub.