apache/beam · error · java.lang.IllegalArgumentException

Expected a Java primitive value but received

Error message

Expected a Java primitive value but received 

What it means

JavaClassLookupTransformProvider decodes constructor arguments that arrive as Beam Rows back into Java objects. When the target constructor parameter is a primitive/wrapper/String, the decoder checks that the value supplied in the Row is also a primitive/wrapper/String. If the Row cell holds a different type (e.g. a Row or a List), it throws IllegalArgumentException.

Source

Thrown at sdks/java/expansion-service/src/main/java/org/apache/beam/sdk/expansion/service/JavaClassLookupTransformProvider.java:338

        @Nullable Row parameterRow = constructorRow.getRow(i);
        Schema schema = getParameterSchema(parameterClass);
        if (schema == null) {
          throw new RuntimeException("Could not determine a schema for type " + parameterClass);
        }
        if (parameterRow != null && !parameterRow.getSchema().assignableTo(schema)) {
          return false;
        }
      }
    }
    return true;
  }

  @SuppressWarnings("argument")
  private @Nullable Object getDecodedValueFromRow(
      Class<?> type, Object valueFromRow, @Nullable Type genericType) {
    if (isPrimitiveOrWrapperOrString(type)) {
      if (!isPrimitiveOrWrapperOrString(valueFromRow.getClass())) {
        throw new IllegalArgumentException(
            "Expected a Java primitive value but received " + valueFromRow);
      }
      return valueFromRow;
    } else if (type.isArray()) {
      Class<?> arrayComponentClass = type.getComponentType();
      return getDecodedArrayValueFromRow(arrayComponentClass, valueFromRow);
    } else if (Collection.class.isAssignableFrom(type)) {
      List<Object> originalList = (List) valueFromRow;
      List<Object> decodedList = new ArrayList<>();
      for (Object obj : originalList) {
        if (genericType instanceof ParameterizedType) {
          Class<?> elementType =
              (Class<?>) ((ParameterizedType) genericType).getActualTypeArguments()[0];
          decodedList.add(getDecodedValueFromRow(elementType, obj, null));
        } else {
          throw new RuntimeException("Could not determine the generic type of the list");
        }
      }

View on GitHub (pinned to 12126d8942)

Solutions

  1. Fix the constructor schema so the field type matches the Java parameter type (primitive/wrapper/String vs ROW/ARRAY).
  2. Verify the parameter order/field mapping so primitive parameters line up with scalar Row fields.
  3. If the value is genuinely structured, change the constructor parameter to a schema-registered class instead of a primitive.
  4. Wrap getParameterValues/parameterValue in try-catch on IllegalArgumentException and fail the expansion request with a clear schema-mismatch message.

Example fix

// before: Row field is a nested Row but constructor expects long
Row.ofSchema(constructorSchema, Arrays.asList(Row.of(...), 42L))
// after: supply a scalar matching the constructor parameter type
Row.ofSchema(constructorSchema, Arrays.asList("name", 42L))
Defensive patterns

Strategy: validation

Validate before calling

boolean isScalar(Object v) { return v instanceof String || v instanceof Number || v instanceof Boolean || v instanceof Character; }
// verify each constructorSchema field is scalar before calling the expansion service

Type guard

boolean matchesPrimitiveParam(Class<?> param, Object rowValue) { return (param.isPrimitive() || Number.class.isAssignableFrom(param) || param == String.class) && isScalar(rowValue); }

Prevention

When it happens

Trigger: Calling the expansion service to construct a PTransform whose constructor takes a primitive/wrapper/String parameter, but the constructorSchema Row contains a non-primitive value (nested Row, List, or byte array) at that field position.

Common situations: Schema field typed as ROW or ARRAY in the payload while the Java constructor expects int/long/String; cross-language pipeline where the constructing SDK serializes a struct but the Java class expects a scalar; type drift after regenerating the constructor schema.

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