apache/beam · error · RuntimeException

Expected to find a single mapping constructor method but fou

Error message

Expected to find a single mapping constructor method but found ${mappingConstructorMethods.size()} Payload was ${payload}

What it means

findMappingConstructorMethod matched multiple methods satisfying the allowlist, arity, and compatibility filters. The provider requires exactly one and throws RuntimeException including the count and the full payload for debugging.

Source

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

  private Method findMappingConstructorMethod(
      Method[] methods, JavaClassLookupPayload payload, AllowedClass allowListClass) {

    Row constructorRow = decodeRow(payload.getConstructorSchema(), payload.getConstructorPayload());

    List<Method> mappingConstructorMethods =
        Arrays.stream(methods)
            .filter(
                m -> isConstructorMethodForName(m, payload.getConstructorMethod(), allowListClass))
            .filter(m -> m.getParameterCount() == payload.getConstructorSchema().getFieldsCount())
            .filter(m -> parametersCompatible(m.getParameters(), constructorRow))
            .collect(Collectors.toList());

    if (mappingConstructorMethods.size() == 0) {
      throw new RuntimeException(
          "Could not find a matching constructor method. When using field names, make sure they "
              + "are available in the compiled Java class.");
    } else if (mappingConstructorMethods.size() != 1) {
      throw new RuntimeException(
          "Expected to find a single mapping constructor method but found "
              + mappingConstructorMethods.size()
              + " Payload was "
              + payload);
    }
    return mappingConstructorMethods.get(0);
  }

  @AutoValue
  public abstract static class AllowList {

    public static AllowList nothing() {
      return create(ALLOW_LIST_VERSION, Collections.emptyList());
    }

    public static AllowList everything() {
      return create(
          ALLOW_LIST_VERSION,

View on GitHub (pinned to 12126d8942)

Solutions

  1. Keep exactly one overload with the given name and arity; delete or rename extra overloads.
  2. Use distinct @MultiLanguageConstructorMethod names for each variant.
  3. Tighten parameter types so only one method is parametersCompatible with the Row.
  4. Catch RuntimeException and use the embedded payload to identify which name/arity is ambiguous.

Example fix

// before
static T create(int a, String b) {...}
static T create(long a, String b) {...}
// after
static T create(long a, String b) {...}
Defensive patterns

Strategy: try-catch

Validate before calling

long matches = Arrays.stream(Target.class.getMethods()).filter(m -> m.getName().equals(name)).filter(m -> m.getParameterCount() == schema.getFieldsCount()).count(); if (matches != 1) throw new IllegalStateException("Expected 1 matching method, found " + matches);

Try / catch

try { method(payload); } catch (RuntimeException e) { if (e.getMessage().startsWith("Expected to find a single mapping constructor method")) { /* dedupe overloads or rename */ } throw e; }

Prevention

When it happens

Trigger: Overloaded methods with the same name and arity (both allowed and compatible with the Row), e.g. (int, String) vs (long, String) overloads, or the same name matched via both the annotation branch and the name branch.

Common situations: Adding overloads for convenience to existing constructor methods; autoboxing widening making several overloads compatible; duplicate @MultiLanguageConstructorMethod names on multiple methods.

Understand the failure class

Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.

Related errors


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