apache/beam · error · RuntimeException

Cannot infer schema from unparameterized map.

Error message

Cannot infer schema from unparameterized map.

What it means

When fieldFromType infers a schema field from a java.util.Map-typed field, it needs the map's type parameters to build FieldType.map(keyType, valueType). If the Map type is raw (no generic parameters), the key/value types cannot be inferred and this RuntimeException is thrown.

Solutions

  1. Parameterize the map field with concrete generic types, e.g. Map<String, Integer>.
  2. If generics cannot be added, supply the schema explicitly (Schema.builder().addMapField(...)) instead of inferring.
  3. Note keys must also be primitive schema types; parameterize with a primitive key type like String.
  4. Ensure the TypeDescriptor passed to inference retains type parameters (avoid raw Class-based descriptors).

Example fix

// before
private Map data; // raw map
// after
private Map<String, Integer> data;
Defensive patterns

Strategy: type-guard

Validate before calling

for (java.lang.reflect.Field f : pojoClass.getDeclaredFields()) {
  if (Map.class.isAssignableFrom(f.getType())
      && f.getGenericType() instanceof Class) {
    throw new IllegalArgumentException("Raw Map field: " + f.getName());
  }
}

Type guard

boolean hasParameterizedMap(java.lang.reflect.Field f) {
  return f.getGenericType() instanceof java.lang.reflect.ParameterizedType
      && Map.class.isAssignableFrom(f.getType());
}

Try / catch

try {
  Schema s = Schema.of(pojoClass);
} catch (RuntimeException e) {
  if (e.getMessage() != null && e.getMessage().contains("unparameterized map")) {
    throw new IllegalStateException("Parameterize Map fields, e.g. Map<String, Integer>", e);
  }
  throw e;
}

Prevention

When it happens

Trigger: Schema inference on a POJO field declared as a raw Map (e.g. `private Map data;` instead of `Map<String, Integer>`), passed via fieldFromType from fieldType/keyType/valueType.

Common situations: Legacy POJOs without generics, code refactored away from generic types, or reflection-supplied types that lose parameterization (e.g. raw types from Object fields).

Understand the failure class

Background: "missing required argument" and "the following required arguments were not provided": what required-argument errors mean and how to fix them — this error's family across 20 libraries.

Related errors


AI-assisted analysis of apache/beam@12126d8942 (2026-09-13). Data as JSON: /api/errors/d7a5091e0a03825c. Report an issue: GitHub.

Appendix: source

Thrown at sdks/java/core/src/main/java/org/apache/beam/sdk/schemas/utils/StaticSchemaInference.java:181

      }
    } else if (type.isSubtypeOf(TypeDescriptor.of(Map.class))) {
      TypeDescriptor<Collection<?>> map = type.getSupertype(Map.class);
      if (map.getType() instanceof ParameterizedType) {
        ParameterizedType ptype = (ParameterizedType) map.getType();
        java.lang.reflect.Type[] params = ptype.getActualTypeArguments();
        checkArgument(params.length == 2);
        FieldType keyType =
            fieldFromType(
                TypeDescriptor.of(params[0]), fieldValueTypeSupplier, alreadyVisitedSchemas);
        FieldType valueType =
            fieldFromType(
                TypeDescriptor.of(params[1]), fieldValueTypeSupplier, alreadyVisitedSchemas);
        checkArgument(
            keyType.getTypeName().isPrimitiveType(),
            "Only primitive types can be map keys. type: " + keyType.getTypeName());
        return FieldType.map(keyType, valueType);
      } else {
        throw new RuntimeException("Cannot infer schema from unparameterized map.");
      }
    } else if (type.isSubtypeOf(TypeDescriptor.of(CharSequence.class))) {
      return FieldType.STRING;
    } else if (type.isSubtypeOf(TypeDescriptor.of(ReadableInstant.class))) {
      return FieldType.DATETIME;
    } else if (type.getRawType().equals(LocalDate.class)) {
      return FieldType.logicalType(SqlTypes.DATE);
    } else if (type.getRawType().equals(LocalTime.class)) {
      return FieldType.logicalType(SqlTypes.TIME);
    } else if (type.getRawType().equals(LocalDateTime.class)) {
      return FieldType.logicalType(SqlTypes.DATETIME);
    } else if (type.getRawType().equals(java.time.Instant.class)) {
      return FieldType.logicalType(new NanosInstant());
    } else if (type.getRawType().equals(UUID.class)) {
      return FieldType.logicalType(SqlTypes.UUID);
    } else if (type.isSubtypeOf(TypeDescriptor.of(ByteBuffer.class))) {
      return FieldType.BYTES;
    } else if (type.isSubtypeOf(TypeDescriptor.of(Iterable.class))) {

View on GitHub (pinned to 12126d8942)