apache/dubbo · error · IllegalArgumentException

Expect only one but found ${size} matched constructors for t

Error message

Expect only one but found ${size} matched constructors for type: ${type}, matched constructors: ${matchedConstructors}

What it means

Thrown by InstantiationStrategy.instantiate when more than one public constructor matches Dubbo's rule (all parameters assignable to ScopeModel subclasses, after removing the default constructor). Dubbo picks a single matched constructor to inject scope models into; multiple candidates are ambiguous, so it refuses to guess and lists them. IllegalArgumentException, surfaced wrapped as ScopeBeanException by callers.

Source

Thrown at dubbo-common/src/main/java/org/apache/dubbo/common/beans/support/InstantiationStrategy.java:77

        List<Constructor<?>> matchedConstructors = new ArrayList<>();
        Constructor<?>[] declaredConstructors = type.getConstructors();
        for (Constructor<?> constructor : declaredConstructors) {
            if (isMatched(constructor)) {
                matchedConstructors.add(constructor);
            }
        }
        // remove default constructor from matchedConstructors
        if (defaultConstructor != null) {
            matchedConstructors.remove(defaultConstructor);
        }

        // match order:
        // 1. the only matched constructor with parameters
        // 2. default constructor if absent

        Constructor<?> targetConstructor;
        if (matchedConstructors.size() > 1) {
            throw new IllegalArgumentException("Expect only one but found " + matchedConstructors.size()
                    + " matched constructors for type: " + type.getName() + ", matched constructors: "
                    + matchedConstructors);
        } else if (matchedConstructors.size() == 1) {
            targetConstructor = matchedConstructors.get(0);
        } else if (defaultConstructor != null) {
            targetConstructor = defaultConstructor;
        } else {
            throw new IllegalArgumentException("None matched constructor was found for type: " + type.getName());
        }

        // create instance with arguments
        Class<?>[] parameterTypes = targetConstructor.getParameterTypes();
        Object[] args = new Object[parameterTypes.length];
        for (int i = 0; i < parameterTypes.length; i++) {
            args[i] = getArgumentValueForType(parameterTypes[i]);
        }
        return (T) targetConstructor.newInstance(args);
    }

View on GitHub (pinned to 3a3043227f)

Solutions

  1. Keep exactly one public constructor that takes ScopeModel arguments (consolidate onto ScopeModel or ApplicationModel).
  2. If two constructors are genuinely needed, make all but one non-public or parameterized by non-ScopeModel types so only one matches isMatched.
  3. Prefer a single (ScopeModel) constructor and obtain specific models via scopeModelAccessor inside the bean.
  4. As a fallback, register an explicit Supplier/instance so InstantiationStrategy.instantiate is bypassed.

Example fix

// before
public class MyExt {
    public MyExt(ApplicationModel app) { ... }
    public MyExt(FrameworkModel fw) { ... }  // both match -> ambiguous
}
// after
public class MyExt {
    public MyExt(ScopeModel scope) {
        this.app = scope.getDefaultAppModel();
    }
}
Defensive patterns

Strategy: validation

Validate before calling

// Ensure at most one ScopeModel-arg public constructor exists
boolean singleScopeConstructor(Class<?> c) {
    int matched = 0;
    Constructor<?> def = null;
    try { def = c.getConstructor(); } catch (NoSuchMethodException ignored) {}
    for (Constructor<?> ctor : c.getConstructors()) {
        if (ctor.equals(def)) continue;
        boolean ok = true;
        for (Class<?> p : ctor.getParameterTypes())
            ok &= org.apache.dubbo.rpc.model.ScopeModel.class.isAssignableFrom(p);
        if (ok) matched++;
    }
    return matched <= 1;
}

Prevention

When it happens

Trigger: A class instantiated via InstantiationStrategy (SPI extension or registered bean) that has two or more public constructors whose parameters are all ScopeModel/ApplicationModel/FrameworkModel/ModuleModel types. E.g. constructors (ApplicationModel) and (FrameworkModel) both pass isMatched.

Common situations: Extension classes written with multiple scope-model constructors; refactoring that added a second constructor taking a different ScopeModel subclass; SPI implementation upgraded to support multiple model types simultaneously.

Related errors


AI-assisted analysis of apache/dubbo@3a3043227f (2026-08-14). Data as JSON: /api/errors/cec26004731910b1. Report an issue: GitHub.