apache/beam · error · java.lang.RuntimeException

Builder method name has to be explicitly allowed

Error message

Builder method name  has to be explicitly allowed

What it means

A builder method matched the requested name (either directly or by the withX -> x field-name convention), but the method is not on the service's allowlist. This is the allowlist security check failing for the conventional 'withX'/field-name matching path, distinct from the @MultiLanguageBuilderMethod path.

Solutions

  1. Allowlist the resolved method name (the lower-cased field name form shown in the message) in the expansion service configuration.
  2. Rename your payload to use the exact builder method name and ensure that name is allowlisted.
  3. Confirm with the service operator which builder methods are permitted before building the pipeline payload.

Example fix

// before
payload: {name: "count"}  // withCount not allowlisted
// after: operator adds 'count' (or 'withCount') to allowed builder methods for the transform, then retry
Defensive patterns

Strategy: validation

Validate before calling

String resolved = fieldName.startsWith("with")
    ? Character.toLowerCase(fieldName.charAt(4)) + fieldName.substring(5) : fieldName;
if (!allowList.isAllowedBuilderMethod(resolved)) {
  throw new IllegalStateException("Allowlist the field-name form '" + resolved + "' before expanding");
}

Try / catch

try {
  return getMethod(transform, row, allowList);
} catch (RuntimeException e) {
  if (e.getMessage() != null && e.getMessage().contains("has to be explicitly allowed")) {
    throw new SecurityException("Method name not allowlisted: " + e.getMessage(), e);
  }
  throw e;
}

Prevention

When it happens

Trigger: Expansion payload names a builder method via field-name convention (e.g. 'count' matching withCount) that exists on the transform but is not in the expansion service's allowed builder methods list.

Common situations: Cross-language users referencing Java transform builder methods by field name without the service operator having allowlisted them; allowlist updated for the exact method name but not the lower-cased field-name variant expected here.

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


AI-assisted analysis of apache/beam@12126d8942 (2026-09-13). Data as JSON: /api/errors/82ebdaa66124b70f. Report an issue: GitHub.

Appendix: source

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

        }
      }
    }

    // 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);
    }
    if (match && !allowListClass.isAllowedBuilderMethod(consideredMethodName)) {
      throw new RuntimeException(
          "Builder method name " + consideredMethodName + " has to be explicitly allowed");
    }
    return match;
  }

  private Method getMethod(
      PTransform<PInput, POutput> transform,
      BuilderMethod builderMethod,
      AllowedClass allowListClass) {

    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());

View on GitHub (pinned to 12126d8942)