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

The default case of the iterable-type switch in addIterableToMutationBuilder throws this IllegalArgumentException when the iterable element TypeName is not one of the supported array element types (STRING, INT64, BOOLEAN, FLOAT64, ROW, TIMESTAMP, DATE, logical/date-time variants). The row cannot be translated to a Spanner struct/mutation.

Source

Thrown at sdks/java/io/google-cloud-platform/src/main/java/org/apache/beam/sdk/io/gcp/spanner/MutationUtils.java:408

        } else {
          throw new IllegalArgumentException(
              String.format("Unsupported logical type in iterable: %s", identifier));
        }
        break;
      case DATETIME:
        if (iterable == null) {
          mutationBuilder.set(column).toDateArray(null);
        } else {
          mutationBuilder
              .set(column)
              .toTimestampArray(
                  StreamSupport.stream(iterable.spliterator(), false)
                      .map(datetime -> Timestamp.parseTimestamp(datetime.toString()))
                      .collect(toList()));
        }
        break;
      default:
        throw new IllegalArgumentException(
            String.format(
                "Unsupported iterable type '%s' while translating row to struct.",
                beamIterableType.getTypeName()));
    }
  }

  public static Row createRowFromMutation(Schema schema, Mutation mutation) {
    Map<String, Object> mutationHashMap = new HashMap<>();
    mutation
        .asMap()
        .forEach(
            (column, value) -> mutationHashMap.put(column, convertValueToBeamFieldType(value)));
    return Row.withSchema(schema).withFieldValues(mutationHashMap).build();
  }

  public static Object convertValueToBeamFieldType(Value value) {
    switch (value.getType().getCode()) {
      case BOOL:

View on GitHub (pinned to 12126d8942)

Solutions

  1. Convert the iterable's elements to a supported Spanner array element type (STRING, INT64, FLOAT64, BOOLEAN, TIMESTAMP, DATE, or ROW/struct).
  2. For nested iterables, flatten or serialize to a JSON string or a ROW array instead.
  3. Inspect the offending TypeName from the message and add an explicit mapping in your pipeline before the Spanner write.

Example fix

// before: ITERABLE<ITERABLE<INT32>> field
// after: serialize nested list to JSON string row.apply(... via(r -> r.getIterable("cols").toString()) ...)
Defensive patterns

Strategy: validation

Validate before calling

java.util.Set<Schema.TypeName> ok = java.util.Set.of(
  Schema.TypeName.STRING, Schema.TypeName.INT64, Schema.TypeName.BOOLEAN,
  Schema.TypeName.DOUBLE, Schema.TypeName.ROW, Schema.TypeName.DATETIME, Schema.TypeName.LOGICAL_TYPE);
if (!ok.contains(field.getType().getCollectionElementType().getTypeName())) {
  throw new IllegalStateException("Iterable element type not supported: "
      + field.getType().getCollectionElementType().getTypeName());
}

Try / catch

try { createMutationFromBeamRows(schema, row, table); } catch (IllegalArgumentException e) { if (e.getMessage().contains("Unsupported iterable type")) { /* re-map elements and retry */ } else throw e; }

Prevention

When it happens

Trigger: Writing a Beam Row with an ITERABLE field whose collection element type is e.g. DOUBLE? bytes, FLOAT, INT16/INT32, MAP, or any other non-supported TypeName into Spanner via createMutationFromBeamRows.

Common situations: Nested arrays of byte arrays (BYTES), arrays of arrays (nested iterables), or arrays of uncommon numeric widths being written to Spanner, whose array element types are more restricted.

Understand the failure class

Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.

Related errors


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