apache/beam · error · java.lang.RuntimeException
Builder method has to be explicitly allowed
Error message
Builder method has to be explicitly allowed
What it means
The builder method matched by its @MultiLanguageBuilderMethod name, but that method is not on the expansion service's allowlist, so the service refuses to invoke it. The allowlist (isAllowedBuilderMethod) is a security control preventing arbitrary code execution through the expansion service.
Solutions
- Add the builder method name to the expansion service's allowed-builder-methods allowlist configuration and restart the service.
- If you control the transform, use the standard annotated-constructor/builder registration expected by the service so it is allowlisted.
- Check the allowlist configuration file/format (allowed class/method list) for typos in the method name.
Example fix
// before: expansion service started without allowlist entry java -jar expansion.jar // after java -jar expansion.jar --allowedBuilderMethods=com.example.MyTransform:withCount
Defensive patterns
Strategy: validation
Validate before calling
ExpansionServiceConfig cfg = service.getConfig();
if (!cfg.getAllowedBuilderMethods(transformClass).contains(annotatedMethodName)) {
throw new IllegalStateException("Builder method must be allowlisted: " + annotatedMethodName);
} Try / catch
try {
return getTransform(payload);
} catch (RuntimeException e) {
if (e.getMessage() != null && e.getMessage().contains("has to be explicitly allowed")) {
throw new SecurityException("Builder method not allowlisted on expansion service: " + payload.getName(), e);
}
throw e;
} Prevention
- Maintain the allowlist as code/config reviewed alongside the transform.
- Document the allowed builder methods for operators of the expansion service.
- Add a CI check that every @MultiLanguageBuilderMethod is present in the service allowlist.
- Prefer allowing specific methods over broad class-level grants.
When it happens
Trigger: Requesting expansion of a transform whose payload names a @MultiLanguageBuilderMethod-annotated method that was not explicitly added to the configured allowlist of the expansion service.
Common situations: Using XLang (e.g. Python/Go calling a Java transform) without registering the builder method in the expansion service's allowed builder methods configuration; adding new builder methods to a transform but forgetting to update the allowlist.
Understand the failure class
Background: Permission denied / not authorized / 403 Forbidden: access-control rejections when the caller lacks the required role, grant, or ownership — this error's family across 18 libraries.
Related errors
- Builder method name has to be explicitly allowed
- Constructor method needs to be explicitly allowed
- cannot register Coder : method named 'of' with arguments…
- Cannot unzip file containing an entry with ".." in the…
- Could not determine a schema for type
AI-assisted analysis of apache/beam@12126d8942 (2026-09-13).
Data as JSON: /api/errors/8c38d08c6cf20d1b.
Report an issue: GitHub.
Appendix: source
Thrown at sdks/java/expansion-service/src/main/java/org/apache/beam/sdk/expansion/service/JavaClassLookupTransformProvider.java:182
+ " with parameter schema "
+ builderMethod.getSchema(),
e);
}
}
return transform;
}
private boolean isBuilderMethodForName(
Method method, String nameFromPayload, AllowedClass allowListClass) {
// Lookup based on method annotations
for (Annotation annotation : method.getAnnotations()) {
if (annotation instanceof MultiLanguageBuilderMethod) {
if (nameFromPayload.equals(((MultiLanguageBuilderMethod) annotation).name())) {
if (allowListClass.isAllowedBuilderMethod(nameFromPayload)) {
return true;
} else {
throw new RuntimeException(
"Builder method " + nameFromPayload + " has to be explicitly allowed");
}
}
}
}
// Lookup based on the method name.
boolean match = method.getName().equals(nameFromPayload);
String consideredMethodName = method.getName();
// We provide a simplification for common Java builder pattern naming convention where builder
// methods start with "with". In this case, for a builder method name in the form "withXyz",
// users may just use "xyz". If additional updates to the method name are needed the transform
// has to be updated by adding annotations.
if (!match && consideredMethodName.length() > 4 && consideredMethodName.startsWith("with")) {
consideredMethodName =
consideredMethodName.substring(4, 5).toLowerCase() + consideredMethodName.substring(5);
match = consideredMethodName.equals(nameFromPayload);View on GitHub (pinned to 12126d8942)