apache/dubbo · error · RpcException

Can not merge result: {e.getMessage()}

Error message

Can not merge result: {e.getMessage()}

What it means

Thrown by MergeableClusterInvoker when the reflected merge method (merger=".method") is found but invoking it throws. Method.invoke can raise IllegalAccessException (access reduced after setAccessible restrictions), IllegalArgumentException (argument type mismatch), or InvocationTargetException (the merge method itself blew up). The original exception message is appended.

Source

Thrown at dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/support/MergeableClusterInvoker.java:173

                        + returnType.getName() + " ]");
            }
            if (!Modifier.isPublic(method.getModifiers())) {
                method.setAccessible(true);
            }
            result = resultList.remove(0).getValue();
            try {
                if (method.getReturnType() != void.class
                        && method.getReturnType().isAssignableFrom(result.getClass())) {
                    for (Result r : resultList) {
                        result = method.invoke(result, r.getValue());
                    }
                } else {
                    for (Result r : resultList) {
                        method.invoke(result, r.getValue());
                    }
                }
            } catch (Exception e) {
                throw new RpcException("Can not merge result: " + e.getMessage(), e);
            }
        } else {
            Merger resultMerger;
            ApplicationModel applicationModel = ScopeModelUtil.getApplicationModel(
                    invocation.getModuleModel().getApplicationModel());

            if (ConfigUtils.isDefault(merger)) {
                resultMerger = applicationModel
                        .getBeanFactory()
                        .getBean(MergerFactory.class)
                        .getMerger(returnType);
            } else {
                resultMerger = applicationModel.getExtensionLoader(Merger.class).getExtension(merger);
            }
            if (resultMerger != null) {
                List<Object> rets = new ArrayList<>(resultList.size());
                for (Result r : resultList) {
                    rets.add(r.getValue());

View on GitHub (pinned to 3a3043227f)

Solutions

  1. Make the merge method public so no setAccessible is required, avoiding IllegalAccessException under strict module encapsulation.
  2. Ensure the merge method parameter type exactly matches the service return type (no raw/generic erasure mismatch).
  3. Make the merge method null-safe: guard against null fields/values from any group before combining.
  4. Add --add-opens on the relevant package if you cannot change the third-party return type, as a last resort.

Example fix

// before: non-public merge + brittle null handling
void merge(Stats other) { this.count += other.count; }

// after: public, null-safe
public Stats merge(Stats other) {
    if (other == null) return this;
    this.count += other.count;
    return this;
}
Defensive patterns

Strategy: validation

Validate before calling

// Confirm the merge method is public and null-safe before relying on it
Method m = ReturnType.class.getMethod("merge", ReturnType.class);
if (!Modifier.isPublic(m.getModifiers())) {
    throw new IllegalStateException("merge method must be public");
}

Try / catch

try {
    return aggregator.call(req);
} catch (RpcException e) {
    if (e.getMessage() != null && e.getMessage().startsWith("Can not merge result:")) {
        log.error("merge method threw; check access/null-safety", e);
    }
    throw e;
}

Prevention

When it happens

Trigger: merger=".method" resolves to a method whose visibility cannot be widened under the JVM's module/access rules; or the merge method receives a value whose runtime class is not assignable to its parameter (generic erasure mismatch); or the merge method body throws an exception when combining two real results.

Common situations: JDK 16+ strong encapsulation blocking setAccessible(true) on a non-public merge method in a library JAR; merge method declared with a wider/different parameter type than the actual return type; merge method throws NPE on null fields when one group returns empty data; record/immutable return types whose 'merge' mutates state unexpectedly.

Related errors


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