apache/dubbo · error · RpcException

Failed to invoke service {entry.getKey()}: {e.getMessage()}

Error message

Failed to invoke service {entry.getKey()}: {e.getMessage()}

What it means

Thrown by MergeableClusterInvoker when fetching the async result of one group's invocation throws any non-RpcException (the get(Integer.MAX_VALUE, ...) on a per-group future fails). MergeableCluster fans a call out across all configured groups and aggregates; if one group's async future fails to resolve, the whole merge is aborted with this wrapping RpcException naming the failing group's service key.

Source

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

        List<Result> resultList = new ArrayList<>(results.size());

        for (Map.Entry<String, Result> entry : results.entrySet()) {
            Result asyncResult = entry.getValue();
            try {
                Result r = asyncResult.get(Integer.MAX_VALUE, TimeUnit.MILLISECONDS);
                if (r.hasException()) {
                    log.error(
                            LoggerCodeConstants.CLUSTER_FAILED_GROUP_MERGE,
                            "Invoke " + getGroupDescFromServiceKey(entry.getKey()) + " failed: "
                                    + r.getException().getMessage(),
                            "",
                            r.getException().getMessage());
                } else {
                    resultList.add(r);
                }
            } catch (Exception e) {
                throw new RpcException("Failed to invoke service " + entry.getKey() + ": " + e.getMessage(), e);
            }
        }

        if (resultList.isEmpty()) {
            return AsyncRpcResult.newDefaultAsyncResult(invocation);
        } else if (resultList.size() == 1) {
            return AsyncRpcResult.newDefaultAsyncResult(resultList.get(0).getValue(), invocation);
        }

        if (returnType == void.class) {
            return AsyncRpcResult.newDefaultAsyncResult(invocation);
        }

        if (merger.startsWith(".")) {
            merger = merger.substring(1);
            Method method;
            try {
                method = returnType.getMethod(merger, returnType);

View on GitHub (pinned to 3a3043227f)

Solutions

  1. Identify the failing group from the embedded service key and verify that group's providers are registered, healthy, and reachable.
  2. Align timeouts: ensure the consumer timeout covers the slowest group so no single group future times out during the merge wait.
  3. Confirm every group exposes the same method signature and serialization is compatible across groups (same interface version).
  4. If partial results are acceptable, consider a custom Cluster/Merger that tolerates a subset of group failures instead of the built-in mergeable cluster.

Example fix

// before: one slow/failed group aborts the entire aggregated call
<dubbo:reference interface="com.acme.Aggregator" group="*" merger="true"/>

// after: ensure all groups share timeout + are healthy; isolate the weak group
<dubbo:reference interface="com.acme.Aggregator" group="a,b" merger="true" timeout="3000"/>
Defensive patterns

Strategy: try-catch

Validate before calling

// Before aggregating, confirm each group has available providers
List<Invoker<T>> live = invokers.stream().filter(Invoker::isAvailable).collect(toList());
if (live.size() < requiredGroupCount) {
    log.warn("not all groups available before merge: {}", live);
}

Try / catch

try {
    return aggregator.call(req);
} catch (RpcException e) {
    if (e.getMessage() != null && e.getMessage().startsWith("Failed to invoke service ")) {
        String failingGroup = extractGroup(e);          // from message
        alertPartialGroupFailure(failingGroup, e);
    }
    throw e;
}

Prevention

When it happens

Trigger: Invoking a method configured with group aggregation (multiple groups, merger= set) where one group's invocation future completes exceptionally with a non-RpcException cause, e.g. a TimeoutException, ExecutionException, or a serialization/decoding error during asyncResult.get(). The failing group's service key is embedded in the message.

Common situations: One provider group is unhealthy/down while others are up (partial outage under merge); per-group timeout misconfiguration causing one future to fail; version skew where one group returns an incompatible type that fails deserialization; registry split-brain leaving one group with stale invokers.

Related errors


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