apache/beam · error · IllegalArgumentException

Expected Map for type " + fieldType + ", but got: " +…

Error message

Expected Map for type " + fieldType + ", but got: " + value.getClass().getName()

What it means

MongoDbUtils.convertFromBsonValue is converting a BSON value into a Beam value for a schema field whose FieldType is MAP. It requires the raw Java value to already be a java.util.Map (e.g. a BSON Document), but the runtime value is some other class. This is a programming/configuration mismatch: the declared Beam schema does not match the shape of the data coming out of MongoDB.

Solutions

  1. Inspect the offending MongoDB document and correct the Beam schema FieldType (e.g. use a ROW or STRING type instead of MAP) to match the stored data.
  2. If the value is an array, change the field type to ARRAY<MAP<STRING,STRING>> so the iterable is unwrapped before the MAP case runs.
  3. Add a pre-conversion normalization step (custom DoFn) that converts non-Map BSON values (e.g. Document wrapped in other types) into java.util.Map before toRow.
  4. Pin/align the MongoDB Java driver version so decoded values are org.bson.Document (a Map) as expected.

Example fix

// before: schema field declared as MAP but data is scalar
fields.add(Field.of("attrs", FieldType.map(FieldType.STRING)));
// after: match the actual stored type (e.g. string JSON)
fields.add(Field.of("attrs", FieldType.STRING));
Defensive patterns

Strategy: validation

Validate before calling

if (!(bsonValue instanceof Map) && fieldType.getTypeName().equals(TypeName.MAP)) {
  throw new IllegalStateException("Field expects a document but got: " + bsonValue.getClass());
}

Type guard

static boolean isConvertibleMap(Object v) { return v instanceof java.util.Map; }

Try / catch

try {
  Row row = MongoDbUtils.toRow(doc, schema);
} catch (IllegalArgumentException e) {
  LOG.error("BSON->Row conversion failed for schema {}: {}", schema, e.getMessage());
  throw e;
}

Prevention

When it happens

Trigger: A field in the Beam schema is declared with FieldType MAP, but convertFromBsonValue receives a non-Map object for that field — e.g. the BSON value is a scalar, array, Document subclass variant, or a decoded type not implementing Map. Reached via toRow or recursively via convertFromBsonValue for nested collections.

Common situations: Schema auto-inference from a changed MongoDB document; storing a string or ObjectId where a map is expected; nested arrays of maps where the element type was inferred as MAP instead of ARRAY<MAP>; driver version changes altering decoded classes (Document vs RawBsonDocument).

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/9640a8b38761777e. Report an issue: GitHub.

Appendix: source

Thrown at sdks/java/io/mongodb/src/main/java/org/apache/beam/sdk/io/mongodb/MongoDbUtils.java:173

              "Expected Iterable for type "
                  + fieldType
                  + ", but got: "
                  + value.getClass().getName());
        }
        Iterable<?> iterable = (Iterable<?>) value;
        List<@Nullable Object> rowList = new ArrayList<>();
        FieldType elementType = fieldType.getCollectionElementType();
        if (elementType == null) {
          throw new IllegalArgumentException(
              "Collection element type cannot be null for type: " + fieldType);
        }
        for (Object item : iterable) {
          rowList.add(convertFromBsonValue(item, elementType));
        }
        return rowList;
      case MAP:
        if (!(value instanceof Map)) {
          throw new IllegalArgumentException(
              "Expected Map for type " + fieldType + ", but got: " + value.getClass().getName());
        }
        Map<?, ?> map = (Map<?, ?>) value;
        Map<String, @Nullable Object> rowMap = new HashMap<>();
        FieldType valueType = fieldType.getMapValueType();
        if (valueType == null) {
          throw new IllegalArgumentException(
              "Map value type cannot be null for type: " + fieldType);
        }
        for (Map.Entry<?, ?> entry : map.entrySet()) {
          rowMap.put(
              String.valueOf(entry.getKey()), convertFromBsonValue(entry.getValue(), valueType));
        }
        return rowMap;
      case ROW:
        Schema rowSchema = fieldType.getRowSchema();
        if (rowSchema == null) {
          throw new IllegalArgumentException("Row schema cannot be null for type: " + fieldType);

View on GitHub (pinned to 12126d8942)