apache/beam · error · java.lang.IllegalArgumentException
Could not determine the row function for class
Error message
Could not determine the row function for class
What it means
For a constructor parameter whose value arrives as a Beam Row, the decoder looks up a fromRow function in the SchemaRegistry for the target class. If the class has no registered schema (NoSuchSchemaException), it throws IllegalArgumentException naming the class.
Solutions
- Annotate the class with @DefaultSchema(JavaBeanSchema.class) or another SchemaProvider.
- Explicitly register it: SchemaRegistry.getDefault().getSchemaProvider(MyClass.class) or register(Class, SchemaProvider).
- Make sure the same ClassLoader in the expansion service loads the annotated class.
- Catch IllegalArgumentException and surface 'register a schema for class X' guidance to the pipeline author.
Example fix
// before
public class MyOptions { private String name; ... }
// after
@DefaultSchema(JavaBeanSchema.class)
public class MyOptions { private String name; ... } Defensive patterns
Strategy: validation
Validate before calling
try { SchemaRegistry.getDefault().getSchema(MyClass.class); } catch (NoSuchSchemaException e) { throw new IllegalStateException("Register a schema for MyClass (@DefaultSchema)"); } Try / catch
try { parameterValues(...); } catch (IllegalArgumentException e) { if (e.getMessage().startsWith("Could not determine the row function")) { /* prompt schema registration */ } throw e; } Prevention
- Annotate every constructor parameter type with @DefaultSchema
- Register schemas explicitly in the expansion service main
- Ensure one ClassLoader loads annotated classes
- Test schema lookup for each parameter type at service startup
When it happens
Trigger: A constructor parameter is a POJO/complex type, the payload provides a Row for it, but the class was never registered with a schema (no @DefaultSchema annotation and no SchemaRegistry.register call).
Common situations: Custom PTransform constructor taking a user options/config class that lacks @DefaultSchema; class registered under a different ClassLoader in the expansion service; refactored class name no longer matching the registered schema.
Understand the failure class
Background: Schema validation failed / invalid input schema: payload rejected because its shape doesn't match the expected schema — this error's family across 28 libraries.
Related errors
- Could not determine a valid schema for parameter class
- A list of URNs for overriding transforms was provided but…
- A cannot be expanded
- A transform cannot be initiated using the provided config…
- AVRO schema doesn't match row schema. Row schema
AI-assisted analysis of apache/beam@12126d8942 (2026-09-13).
Data as JSON: /api/errors/095592db1bb88205.
Report an issue: GitHub.
Appendix: source
Thrown at sdks/java/expansion-service/src/main/java/org/apache/beam/sdk/expansion/service/JavaClassLookupTransformProvider.java:364
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");
}
}
return decodedList;
} else if (valueFromRow instanceof Row) {
Row row = (Row) valueFromRow;
SerializableFunction<Row, ?> fromRowFunc;
try {
fromRowFunc = SCHEMA_REGISTRY.getFromRowFunction(type);
} catch (NoSuchSchemaException e) {
throw new IllegalArgumentException(
"Could not determine the row function for class " + type, e);
}
return fromRowFunc.apply(row);
}
throw new RuntimeException("Could not decode the value from Row " + valueFromRow);
}
@SuppressWarnings("argument")
private Object[] getParameterValues(
java.lang.reflect.Parameter[] parameters, Row constrtuctorRow, Type[] genericTypes) {
ArrayList<Object> parameterValues = new ArrayList<>();
for (int i = 0; i < parameters.length; ++i) {
java.lang.reflect.Parameter parameter = parameters[i];
Class<?> parameterClass = parameter.getType();
Object parameterValue =
getDecodedValueFromRow(parameterClass, constrtuctorRow.getValue(i), genericTypes[i]);
parameterValues.add(parameterValue);
}View on GitHub (pinned to 12126d8942)