apache/beam · error · RuntimeException

Expected to find a single mapping constructor but found ${ma

Error message

Expected to find a single mapping constructor but found ${mappingConstructors.size()}

What it means

findMappingConstructor found more than one constructor matching the field count and parameter compatibility. The provider requires exactly one unambiguous mapping constructor and throws RuntimeException with the number found.

Source

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

    return (Object[]) valueTypeArray;
  }

  private Constructor<PTransform<InputT, OutputT>> findMappingConstructor(
      Constructor<?>[] constructors, JavaClassLookupPayload payload) {
    Row constructorRow = decodeRow(payload.getConstructorSchema(), payload.getConstructorPayload());

    List<Constructor<?>> mappingConstructors =
        Arrays.stream(constructors)
            .filter(c -> c.getParameterCount() == payload.getConstructorSchema().getFieldsCount())
            .filter(c -> parametersCompatible(c.getParameters(), constructorRow))
            .collect(Collectors.toList());

    if (mappingConstructors.size() == 0) {
      throw new RuntimeException(
          "Could not find a matching constructor. When using field names, make sure they are "
              + "available in the compiled Java class.");
    } else if (mappingConstructors.size() != 1) {
      throw new RuntimeException(
          "Expected to find a single mapping constructor but found " + mappingConstructors.size());
    }
    return (Constructor<PTransform<InputT, OutputT>>) mappingConstructors.get(0);
  }

  private boolean isConstructorMethodForName(
      Method method, String nameFromPayload, AllowedClass allowListClass) {
    for (Annotation annotation : method.getAnnotations()) {
      if (annotation instanceof MultiLanguageConstructorMethod) {
        if (nameFromPayload.equals(((MultiLanguageConstructorMethod) annotation).name())) {
          if (allowListClass.isAllowedConstructorMethod(nameFromPayload)) {
            return true;
          } else {
            throw new RuntimeException(
                "Constructor method " + nameFromPayload + " needs to be explicitly allowed");
          }
        }
      }

View on GitHub (pinned to 12126d8942)

Solutions

  1. Remove or consolidate overloaded constructors so exactly one matches the schema arity/types.
  2. Make parameter types stricter (avoid int/long overloads) so parametersCompatible yields a single match.
  3. Use a named constructor method (MultiLanguageConstructorMethod) instead of ambiguous constructors.
  4. Catch RuntimeException and log candidate constructors for diagnosis.

Example fix

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

Strategy: try-catch

Validate before calling

long matches = Arrays.stream(Target.class.getConstructors()).filter(c -> c.getParameterCount() == schema.getFieldsCount()).count(); if (matches != 1) throw new IllegalStateException("Expected 1 matching constructor, found " + matches);

Try / catch

try { constructor(payload); } catch (RuntimeException e) { if (e.getMessage().startsWith("Expected to find a single mapping constructor")) { /* remove ambiguity or use a named method */ } throw e; }

Prevention

When it happens

Trigger: A class has overloaded constructors with the same arity and all parameters compatible with the Row (e.g. (int, String) and (long, String), or two same-arity constructors with compatible primitive widening).

Common situations: Classes with convenience overloads; adding a new constructor after the payload schema was generated; autoboxing making several constructors appear compatible.

Related errors


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