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
- Align the Row schema with the actual document field shape (list vs scalar) before conversion
- Normalize scalar values to single-element lists upstream before writing
- Read documents with their natural types first, then coerce with an explicit map transform
- 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
- Coerce scalars to single-element lists upstream
- Keep schemas in sync with the actual document shapes
- Test reads against documents written by older schema versions
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
- Expected Row for nested field.
- Can't cast non-numeric types: +input
- Can't cast numbers to non-numeric type: +output
- Cannot convert BigQuery type '' to '' because the BigQuery…
- Cannot convert value to Row.
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)