apache/beam · error · IllegalArgumentException

Expected Iterable for array field.

Error message

Expected Iterable for array field.

What it means

convertFromJava converts Java values (originating from Firestore Value protos) into Java objects matching the declared FieldType, when mapping documents to Rows. For ARRAY/ITERABLE fields the incoming value must already be an Iterable; any other object type breaks the conversion contract and throws IllegalArgumentException('Expected Iterable for array field.').

Solutions

  1. Align the Row schema with the actual document field shape (list vs scalar) before conversion
  2. Normalize scalar values to single-element lists upstream before writing
  3. Read documents with their natural types first, then coerce with an explicit map transform
  4. Fix the FieldType to match the stored data (e.g. FieldType.STRING instead of iterable)

Example fix

// before
Row row = Row.withSchema(schema).addValues("not-a-list").build(); // scalar in ARRAY slot
// after
Row row = Row.withSchema(schema).addValues(Collections.singletonList("tag")).build();
Defensive patterns

Strategy: type-guard

Validate before calling

Object v = row.getValue("tags");
if (v != null && !(v instanceof Iterable)) {
  v = Collections.singletonList(v); // coerce scalar to list
}

Type guard

static boolean isIterable(Object v) { return v instanceof Iterable; }

Try / catch

try {
  Object out = convertFromJava(value, fieldType);
} catch (IllegalArgumentException e) {
  if (e.getMessage().contains("Expected Iterable")) {
    log.warn("Scalar where array expected; coercing");
  }
}

Prevention

When it happens

Trigger: Reading Firestore documents where a field declared as ARRAY/ITERABLE in the target Schema arrived as a scalar or map (e.g. schema was changed after the data was written, or the wrong schema was supplied to documentToRow/toRow).

Common situations: Schema drift: documents written earlier with scalar values now read with an array-typed schema; passing a document's map value directly instead of its list; mixing up field order when building Rows manually.

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/0f01e7d0455e8f03. Report an issue: GitHub.

Appendix: source

Thrown at sdks/java/io/google-cloud-platform/src/main/java/org/apache/beam/sdk/io/gcp/firestore/FirestoreUtils.java:272

      case BOOLEAN:
        return value;
      case DATETIME:
        if (value instanceof Instant) {
          return value;
        }
        if (value instanceof Number) {
          return new Instant(((Number) value).longValue());
        }
        return Instant.parse(value.toString());
      case BYTES:
        if (value instanceof byte[]) {
          return value;
        }
        return value.toString().getBytes(java.nio.charset.StandardCharsets.UTF_8);
      case ARRAY:
      case ITERABLE:
        if (!(value instanceof Iterable)) {
          throw new IllegalArgumentException("Expected Iterable for array field.");
        }
        FieldType elementType = fieldType.getCollectionElementType();
        if (elementType == null) {
          throw new IllegalArgumentException("Collection element type cannot be null.");
        }
        List<@Nullable Object> rowList = new ArrayList<>();
        for (Object item : (Iterable<?>) value) {
          rowList.add(convertFromJava(item, elementType));
        }
        return rowList;
      case MAP:
        if (!(value instanceof Map)) {
          throw new IllegalArgumentException("Expected Map for map field.");
        }
        FieldType valueType = fieldType.getMapValueType();
        if (valueType == null) {
          throw new IllegalArgumentException("Map value type cannot be null.");
        }

View on GitHub (pinned to 12126d8942)