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

  1. Make the value supplied for the map field a java.util.Map<String, Object> matching the schema's key/value types
  2. Check the field's FieldType in the Schema and align the producer code with it
  3. If the source value is a list of key-value pairs, transform it into a Map before calling toRow
  4. 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

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


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)