apache/beam · error · java.lang.RuntimeException
Expected a schema with a single array field but received
Error message
Expected a schema with a single array field but received
What it means
During parameter compatibility checking, the Java parameter is an array type but the corresponding field in the payload schema row is not an ARRAY type. The service expects an array-typed payload field for every array parameter.
Solutions
- Change the transform's builder method signature to use List<T> instead of T[] (or vice versa) to match the payload type.
- Fix the payload schema so the field's TypeName is ARRAY for that parameter.
- Regenerate the expansion payload with a matching SDK version so type mappings agree.
Example fix
// before
public MyTransform withNames(String[] names) {...}
// after
public MyTransform withNames(List<String> names) {...} // matches ARRAY-typed payload field Defensive patterns
Strategy: type-guard
Validate before calling
for (Parameter p : method.getParameters()) {
if (p.getType().isArray()) {
String t = payloadSchema.getField(p.getName()).getType().getTypeName();
if (t != "ARRAY") throw new IllegalStateException(p.getName() + " must be ARRAY in payload schema");
}
} Type guard
function isArrayTyped(field) { return field.getType().getTypeName() === 'ARRAY'; } Try / catch
try {
return getTransform(payload);
} catch (RuntimeException e) {
if (e.getMessage() != null && e.getMessage().contains("single array field")) {
throw new InvalidExpansionRequest("Payload field type does not match array parameter; use List<T> or ARRAY payload", e);
}
throw e;
} Prevention
- Prefer List<T> over raw arrays T[] in cross-language-exposed builder methods.
- Validate payload schema type names against method signatures before submitting expansion.
- Regenerate payloads whenever the transform signature changes.
- Test parameter compatibility locally with Schema+Row round-trips.
When it happens
Trigger: Expansion payload's schema declares a scalar/repeated type other than ARRAY for a builder-method parameter whose Java type is an array (e.g. int[]).
Common situations: Hand-written or generated payload using a list type where the transform signature uses a raw array (String[]), or vice versa; language mapping differences (Python list -> Java List, not Java array).
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 between types that don't have equivalent…
- Cannot convert value to Row.
- Cannot merge two types: +fieldType1.getTypeName()+ and…
- Converting YAML type
- Could not determine a schema for type
AI-assisted analysis of apache/beam@12126d8942 (2026-09-13).
Data as JSON: /api/errors/5a14c6f361c2a7d8.
Report an issue: GitHub.
Appendix: source
Thrown at sdks/java/expansion-service/src/main/java/org/apache/beam/sdk/expansion/service/JavaClassLookupTransformProvider.java:298
boolean ignoreFieldName =
FIELD_NAME_IGNORE_PATTERN.matcher(parameterFromPayload.getName()).matches();
if (!ignoreFieldName && !paramNameFromReflection.equals(parameterFromPayload.getName())) {
// Parameter name through reflection is from the class file (not through synthesizing,
// hence we can validate names)
return false;
}
Class<?> parameterClass = parameterFromReflection.getType();
if (isPrimitiveOrWrapperOrString(parameterClass)) {
continue;
}
// We perform additional validation for arrays and non-primitive types.
if (parameterClass.isArray()) {
Class<?> arrayFieldClass = parameterClass.getComponentType();
if (parameterFromPayload.getType().getTypeName() != TypeName.ARRAY) {
throw new RuntimeException(
"Expected a schema with a single array field but received "
+ parameterFromPayload.getType().getTypeName());
}
// Following is a best-effort validation that may not cover all cases. Idea is to resolve
// ambiguities as much as possible to determine an exact match for the given set of
// parameters. If there are ambiguities, the expansion will fail.
if (!isPrimitiveOrWrapperOrString(arrayFieldClass)) {
@Nullable Collection<Row> values = constructorRow.getArray(i);
Schema arrayFieldSchema = getParameterSchema(arrayFieldClass);
if (arrayFieldSchema == null) {
throw new RuntimeException("Could not determine a schema for type " + arrayFieldClass);
}
if (values != null) {
@Nullable Row firstItem = values.iterator().next();
if (firstItem != null && !firstItem.getSchema().assignableTo(arrayFieldSchema)) {
return false;
}View on GitHub (pinned to 12126d8942)