apache/beam · error · java.lang.RuntimeException
Expected to find exactly one matching method in transform …
Error message
Expected to find exactly one matching method in transform for BuilderMethod but found
What it means
The name/parameter filtering found more than one candidate builder method matching the requested BuilderMethod, so resolution is ambiguous and the service refuses to pick one. Expansion requires an exact, unique match.
Solutions
- Remove or rename the ambiguous overload in the transform so exactly one builder method matches the payload schema.
- Make the payload parameter schema more specific (correct array vs scalar types) so only one overload is compatible.
- Use an explicit @MultiLanguageBuilderMethod-named method that is unique for the requested operation.
Example fix
// before
public MyTransform withTags(List<String> tags) {...}
public MyTransform withTags(String[] tags) {...}
// after
public MyTransform withTags(List<String> tags) {...} // single overload Defensive patterns
Strategy: validation
Validate before calling
long matches = Stream.of(transformClass.getMethods())
.filter(m -> methodMatchesName(m, name))
.filter(m -> parametersCompatible(m.getParameters(), row))
.filter(m -> PTransform.class.isAssignableFrom(m.getReturnType()))
.count();
if (matches > 1) throw new IllegalStateException("Ambiguous builder method for " + name);
Try / catch
try {
return getTransform(payload);
} catch (RuntimeException e) {
if (e.getMessage() != null && e.getMessage().contains("Expected to find exactly one matching method")) {
throw new InvalidExpansionRequest("Ambiguous overload for builder method; refine payload types", e);
}
throw e;
} Prevention
- Do not overload builder methods that are exposed to cross-language expansion.
- Differentiate overloads by distinct method names instead of parameter types.
- Tighten payload field types (ARRAY vs scalar) so only one overload is compatible.
- Add unit tests that resolve each exposed builder method via the provider.
When it happens
Trigger: A transform exposes overloaded builder methods (same field name, different parameter types/schemas) that all appear compatible with the payload row; withX and field-name convention both resolving to multiple candidates.
Common situations: Adding an overload like withTags(List<String>) alongside withTags(String[]) making the payload ambiguous; payload schema generic enough to match several overloads.
Related errors
- Could not find a matching method in transform for…
- Could not instantiate class
- Could not invoke the builder method on transform with…
- A method marked with SchemaCreate in class
- AutoValue builder class
AI-assisted analysis of apache/beam@12126d8942 (2026-09-13).
Data as JSON: /api/errors/8689fbbbddca2a73.
Report an issue: GitHub.
Appendix: source
Thrown at sdks/java/expansion-service/src/main/java/org/apache/beam/sdk/expansion/service/JavaClassLookupTransformProvider.java:232
Row builderMethodRow = decodeRow(builderMethod.getSchema(), builderMethod.getPayload());
List<Method> matchingMethods =
Arrays.stream(transform.getClass().getMethods())
.filter(m -> isBuilderMethodForName(m, builderMethod.getName(), allowListClass))
.filter(m -> parametersCompatible(m.getParameters(), builderMethodRow))
.filter(m -> PTransform.class.isAssignableFrom(m.getReturnType()))
.collect(Collectors.toList());
if (matchingMethods.size() == 0) {
throw new RuntimeException(
"Could not find a matching method in transform "
+ transform
+ " for BuilderMethod"
+ builderMethod
+ ". When using field names, make sure they are available in the compiled"
+ " Java class.");
} else if (matchingMethods.size() > 1) {
throw new RuntimeException(
"Expected to find exactly one matching method in transform "
+ transform
+ " for BuilderMethod"
+ builderMethod
+ " but found "
+ matchingMethods.size());
}
return matchingMethods.get(0);
}
private static boolean isPrimitiveOrWrapperOrString(java.lang.Class<?> type) {
return ClassUtils.isPrimitiveOrWrapper(type) || type == String.class;
}
private Schema getParameterSchema(Class<?> parameterClass) {
Schema parameterSchema;
try {
parameterSchema = SCHEMA_REGISTRY.getSchema(parameterClass);View on GitHub (pinned to 12126d8942)