apache/beam · error · IllegalArgumentException

Unsupported logical type in iterable: %s

Error message

Unsupported logical type in iterable: %s

What it means

Inside addIterableToMutationBuilder, an iterable whose element type is a LOGICAL_TYPE with an identifier the translator does not recognize reaches the LOGICAL_TYPE case. Only specific logical identifiers (e.g. java.lang.Instant with the toSpannerTimestamp mapping) are supported; anything else throws IllegalArgumentException.

Source

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

        break;
      case LOGICAL_TYPE:
        String identifier = checkNotNull(beamIterableType.getLogicalType()).getIdentifier();
        if (identifier.equals(MicrosInstant.IDENTIFIER)) {
          if (iterable == null) {
            mutationBuilder.set(column).toTimestampArray(null);
          } else {
            mutationBuilder
                .set(column)
                .toTimestampArray(
                    StreamSupport.stream(iterable.spliterator(), false)
                        .map(
                            instant -> {
                              return toSpannerTimestamp((java.time.Instant) instant);
                            })
                        .collect(toList()));
          }
        } 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(

View on GitHub (pinned to 12126d8942)

Solutions

  1. Map the custom logical type to a supported base type (STRING, INT64, etc.) before writing, e.g. via a Map converting elements to their portable representation.
  2. Check the identifier printed in the message against the supported list in MutationUtils and align your logical type identifier.
  3. Upgrade Beam if a newer version supports the logical type, or contribute a mapping case.

Example fix

// before: iterable of custom logical type
rows.apply(SpannerIO.write()...)
// after: convert to supported base type first
PCollection<Row> converted = rows.apply(MapElements.into(...).via(r -> /* convert custom logical type values to String/int64 fields */ r));
Defensive patterns

Strategy: validation

Validate before calling

Schema.FieldType el = field.getType().getCollectionElementType();
if (el != null && el.getTypeName() == Schema.TypeName.LOGICAL_TYPE) {
  String id = el.getLogicalType().getIdentifier();
  if (!java.util.Set.of("Instant", "DateTime", "LocalDate").contains(id)) {
    throw new IllegalStateException("Unsupported logical type in iterable: " + id);
  }
}

Try / catch

try { write.apply(...); } catch (IllegalArgumentException e) { if (e.getMessage().startsWith("Unsupported logical type in iterable")) { /* convert to base type */ } else throw e; }

Prevention

When it happens

Trigger: An ITERABLE field whose element type is Schema.FieldType.logicalType with an identifier other than the supported ones (e.g. a custom LogicalType like a bespoke enum or decimal logical type) is written to Spanner.

Common situations: Users define custom Beam LogicalTypes (money, json, custom enums) and try to write arrays of them to Spanner; Beam version changes add new built-in logical types not yet mapped by the Spanner IO.

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/14f229acdf1a2e24. Report an issue: GitHub.