apache/beam · error · IllegalArgumentException
Unsupported iterable type '%s' while translating row to stru
Error message
Unsupported iterable type '%s' while translating row to struct.
What it means
addIterableToStructBuilder translates Beam array (iterable) fields into Spanner array values. If the element type of the iterable has no case in the switch, this IllegalArgumentException reports the unsupported element type. Only scalar element types (INT64, FLOAT64, STRING, BOOLEAN, TIMESTAMP, DATETIME, etc.) are supported.
Source
Thrown at sdks/java/io/google-cloud-platform/src/main/java/org/apache/beam/sdk/io/gcp/spanner/StructUtils.java:349
break;
case STRING:
structBuilder.set(column).toStringArray((Iterable<String>) ((Object) iterable));
break;
// TODO: implement logical date and datetime
case DATETIME:
if (iterable == null) {
structBuilder.set(column).toTimestampArray(null);
} else {
structBuilder
.set(column)
.toTimestampArray(
StreamSupport.stream(iterable.spliterator(), false)
.map(timestamp -> Timestamp.parseTimestamp(timestamp.toString()))
.collect(toList()));
}
break;
default:
throw new IllegalArgumentException(
String.format(
"Unsupported iterable type '%s' while translating row to struct.",
beamIterableType.getTypeName()));
}
}
private static java.time.Instant fromSpannerTimestamp(Timestamp spannerTimestamp) {
long micros = spannerTimestamp.getSeconds() * 1_000_000L + spannerTimestamp.getNanos() / 1_000L;
return java.time.Instant.ofEpochSecond(micros / 1_000_000L, (micros % 1_000_000L) * 1_000L);
}
private static @Nullable Object getStructValue(Struct struct, Schema.Field field) {
String column = field.getName();
Type.Code typeCode = struct.getColumnType(column).getCode();
if (struct.isNull(column)) {
return null;
}
switch (typeCode) {View on GitHub (pinned to 12126d8942)
Solutions
- Flatten or transform the array elements into a supported scalar type (e.g. map DECIMAL elements to STRING).
- Replace array-of-struct fields with JSON-encoded STRING columns.
- Verify the Row schema's collection element type with field.getType().getCollectionElementType() before conversion.
Example fix
// before
Schema.Field.of("prices", Schema.FieldType.array(Schema.FieldType.DECIMAL))
// after
Schema.Field.of("prices", Schema.FieldType.array(Schema.FieldType.FLOAT64)) Defensive patterns
Strategy: type-guard
Type guard
boolean isArrayElementTypeSupported(Schema.FieldType arrayType) {
Schema.FieldType el = arrayType.getCollectionElementType();
return el != null && switch (el.getTypeName()) {
case INT64, FLOAT64, STRING, BOOLEAN, DATETIME -> true;
default -> false;
};
} Prevention
- Use arrays of scalar types only (INT64, FLOAT64, STRING, BOOLEAN, TIMESTAMP).
- Convert arrays of structs/decimals to JSON STRING columns.
- Validate collection element types in a DoFn before conversion.
When it happens
Trigger: Converting a Beam Row with an ARRAY field whose collection element type is unsupported (e.g. array of DECIMAL or array of ROW) into a Spanner Struct via beamRowToStruct.
Common situations: Arrays of decimals/numerics from BigQuery pipelines; nested arrays produced by earlier transforms; arrays of rows from join results.
Related errors
- Error processing struct to row: {e.getMessage()}
- Unsupported beam type '%s' while translating row to struct.
- Unable to translate beam type %s to Spanner type
- Column %s has array of arrays which is prohibited in Spanner
- Unsupported spanner array type %s for column %s.
AI-assisted analysis of apache/beam@12126d8942 (2026-09-13).
Data as JSON: /api/errors/3910a7352fa758fc.
Report an issue: GitHub.