apache/dubbo · error · RpcException

mock error : {mt.getMessage()}, invoke error is :{StringUtil

Error message

mock error : {mt.getMessage()}, invoke error is :{StringUtils.toString(t)}

What it means

Thrown by MockClusterInvoker.doMockInvoke when the mock invocation itself fails with a non-business RpcException (mockException.isBiz() is false). The original real-invocation error (passed in as 'e') is appended via getMockExceptionMessage so both the mock failure and the triggering failure are visible. This means fail-mock fallback was attempted but the mock path also failed at the transport/cluster layer.

Source

Thrown at dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/support/wrapper/MockClusterInvoker.java:174

        Result result;
        Invoker<T> mockInvoker;

        RpcInvocation rpcInvocation = (RpcInvocation) invocation;
        rpcInvocation.setInvokeMode(RpcUtils.getInvokeMode(getUrl(), invocation));

        List<Invoker<T>> mockInvokers = selectMockInvoker(invocation);
        if (CollectionUtils.isEmpty(mockInvokers)) {
            mockInvoker = (Invoker<T>) new MockInvoker(getUrl(), directory.getInterface());
        } else {
            mockInvoker = mockInvokers.get(0);
        }
        try {
            result = mockInvoker.invoke(invocation);
        } catch (RpcException mockException) {
            if (mockException.isBiz()) {
                result = AsyncRpcResult.newDefaultAsyncResult(mockException.getCause(), invocation);
            } else {
                throw new RpcException(
                        mockException.getCode(), getMockExceptionMessage(e, mockException), mockException.getCause());
            }
        } catch (Throwable me) {
            throw new RpcException(getMockExceptionMessage(e, me), me.getCause());
        }
        if (setFutureWhenSync || rpcInvocation.getInvokeMode() != InvokeMode.SYNC) {
            // set server context
            RpcContext.getServiceContext()
                    .setFuture(new FutureAdapter<>(((AsyncRpcResult) result).getResponseFuture()));
        }
        return result;
    }

    private String getMockExceptionMessage(Throwable t, Throwable mt) {
        String msg = "mock error : " + mt.getMessage();
        if (t != null) {
            msg = msg + ", invoke error is :" + StringUtils.toString(t);
        }

View on GitHub (pinned to 3a3043227f)

Solutions

  1. Validate the mock configuration syntax: mock="return VALUE", mock="throw", mock="force:return VALUE", or a fully-qualified MockImpl class name that exists.
  2. Ensure the mock implementation class (if specified) is on the classpath and implements the service interface.
  3. Distinguish the two errors in the message: fix the underlying real-invocation error (first cause) since the mock only ran because the real call already failed.
  4. Use mock="force:return" during tests to isolate whether the mock path itself is broken independent of provider state.

Example fix

// before: malformed mock spec causes mock fallback to fail too
<dubbo:reference interface="com.acme.Svc" mock="return {\"ok\":true"/>

// after: valid JSON + force to test the mock path in isolation
<dubbo:reference interface="com.acme.Svc" mock="force:return {&quot;ok&quot;:true}"/>
Defensive patterns

Strategy: try-catch

Validate before calling

// Validate the mock spec syntax before the call
String mock = url.getParameter("mock");
if (mock != null && !(mock.startsWith("return") || mock.startsWith("force:return")
        || mock.startsWith("throw") || isValidFqcn(mock))) {
    throw new IllegalStateException("malformed mock spec: " + mock);
}

Try / catch

try {
    return service.call(req);
} catch (RpcException e) {
    if (e.getMessage() != null && e.getMessage().startsWith("mock error :")) {
        // both real call and mock failed; inspect combined message + cause
        log.error("fail-mock fallback also failed", e);
    }
    throw e;
}

Prevention

When it happens

Trigger: A service call fails (network/no-provider/timeout) triggering mock fallback (mock= configured), and the mock invocation then also throws a non-biz RpcException, e.g. the mock returns force vs default, mock URL malformed, or the MockInvoker cannot resolve/execute the mock implementation. The re-thrown RpcException carries the mock's code and the combined message.

Common situations: Configuring mock="force:return ..." or mock="throw ..." with a malformed mock spec; mock implementation class missing on classpath; the mock targets a non-existent method; the original failure was no-provider and the mock invoker itself cannot be constructed (selectMockInvoker empty + MockInvoker init fails).

Related errors


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