apache/beam · error · IllegalArgumentException
Expected Map for map field.
Error message
Expected Map for map field.
What it means
FirestoreV1's schema-conversion helper convertFromJava validates that a value destined for a MAP-typed field in the Beam Row schema is actually a java.util.Map. When a different Java type (list, POJO, string) is supplied for a map field, the conversion cannot proceed and this IllegalArgumentException is thrown. It is a type-contract check between the user's Java value and the declared schema field type.
Solutions
- Make the value supplied for the map field a java.util.Map<String, Object> matching the schema's key/value types
- Check the field's FieldType in the Schema and align the producer code with it
- If the source value is a list of key-value pairs, transform it into a Map before calling toRow
- If the field was never intended to be a map, change the Schema FieldType to match the actual value type
Example fix
// before
Schema schema = Schema.of(Field.of("labels", FieldType.map(FieldType.STRING, FieldType.STRING)));
Row row = toRow(Map.of("labels", List.of("a=1")), schema); // throws
// after
Row row = toRow(Map.of("labels", Map.of("a", "1")), schema); Defensive patterns
Strategy: type-guard
Validate before calling
if (!(value instanceof Map)) { throw new IllegalArgumentException("field 'labels' must be a Map"); } Type guard
boolean isStringKeyMap(Object v) { return v instanceof Map && ((Map<?,?>) v).keySet().stream().allMatch(k -> k instanceof String); } Try / catch
try { Row row = FirestoreUtils.toRow(mapValue, schema); } catch (IllegalArgumentException e) { if (e.getMessage().contains("Expected Map")) { /* log field type mismatch, route to dead-letter */ } else { throw e; } } Prevention
- Keep schema field types and producer classes generated from one source (e.g. Schema creation from POJO annotations)
- Unit-test toRow conversions against representative documents
- Validate PCollection schemas early in the pipeline
When it happens
Trigger: Calling FirestoreUtils.toRow / convertFromJava with a PCollection element whose schema declares a field as MAP (e.g. map<string, string>) but whose Java value is not a Map instance — e.g. a List of pairs, a String, or a custom POJO holding map-like data.
Common situations: Users build a Write's schema with a map field but populate it from Firestore document data or a Proto struct converted to the wrong Java type; schema inference mismatched with the actual element class; refactors changed the field type but not the producer code.
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
- Cannot convert value to Row.
- Cannot convert between types that don't have equivalent…
- Cannot merge two types: +fieldType1.getTypeName()+ and…
- Converting YAML type
- Element argument type
AI-assisted analysis of apache/beam@12126d8942 (2026-09-13).
Data as JSON: /api/errors/15859602c04942f3.
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:285
}
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.");
}
Map<String, @Nullable Object> rowMap = new HashMap<>();
for (Map.Entry<?, ?> entry : ((Map<?, ?>) value).entrySet()) {
rowMap.put(String.valueOf(entry.getKey()), convertFromJava(entry.getValue(), valueType));
}
return rowMap;
case ROW:
Schema rowSchema = fieldType.getRowSchema();
if (rowSchema == null) {
throw new IllegalArgumentException("Row schema cannot be null.");
}
if (value instanceof Map) {
return toRow(castToStringKeyMap((Map<?, ?>) value), rowSchema);
}View on GitHub (pinned to 12126d8942)