apache/dubbo · error · RpcException

Interrupted while acquiring read lock for invoker access, ca

Error message

Interrupted while acquiring read lock for invoker access, cause: {cause}

What it means

Thrown by AbstractDirectory.list() when the thread waiting on invokerRefreshReadLock.tryLock(...) is interrupted (InterruptedException). The interrupt status is re-set (Thread.currentThread().interrupt()) and the call aborts with RpcException. This is the expected outcome when the calling thread is cancelled/interrupted during an RPC.

Source

Thrown at dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/directory/AbstractDirectory.java:237

                if (!invokerRefreshReadLock.tryLock(LockUtils.DEFAULT_TIMEOUT, TimeUnit.MILLISECONDS)) {
                    throw new RpcException(
                            "Failed to acquire read lock on invokerRefreshLock within timeout. " + "Timeout: "
                                    + LockUtils.DEFAULT_TIMEOUT + "ms, " + "Lock state: [readLockHeld="
                                    + invokerRefreshLock.getReadLockCount() + ", writeLockHeld="
                                    + invokerRefreshLock.isWriteLocked() + ", writeLockHeldByCurrentThread="
                                    + invokerRefreshLock.isWriteLockedByCurrentThread() + "], Service: "
                                    + getConsumerUrl().getServiceKey());
                }
                lockAcquired = true;
                // use clone to avoid being modified at doList().
                if (invokersInitialized) {
                    availableInvokers = validInvokers.clone();
                } else {
                    availableInvokers = invokers.clone();
                }
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
                throw new RpcException(
                        "Interrupted while acquiring read lock for invoker access, cause: " + e.getMessage(), e);
            } finally {
                if (lockAcquired) {
                    invokerRefreshReadLock.unlock();
                }
            }

            if (routerChain != null) {
                singleChain = routerChain.getSingleChain(getConsumerUrl(), availableInvokers, invocation);
                singleChain.getLock().readLock().lock();
            }
            List<Invoker<T>> routedResult = doList(singleChain, availableInvokers, invocation);
            if (routedResult.isEmpty()) {
                // 2-2 - No provider available.

                logger.warn(
                        CLUSTER_NO_VALID_PROVIDER,
                        "provider server or registry center crashed",

View on GitHub (pinned to 3a3043227f)

Solutions

  1. Treat interruption as cancellation: ensure the caller propagates/cleans interrupt status and the result is discarded (no retry unless intended).
  2. If spurious, investigate who interrupts the RPC thread (timeout interruParser, executor shutdown) and align timeout settings so the lock wait is not the long pole.
  3. Reduce directory lock contention (see error 4) so the read lock is acquired without blocking.

Example fix

// handle interrupt-driven cancellation at the caller
try {
    result = service.foo();
} catch (RpcException e) {
    if (Thread.currentThread().isInterrupted()) {
        // request was cancelled; do not retry blindly
        throw new CancellationException("rpc cancelled");
    }
    throw e;
}
Defensive patterns

Strategy: try-catch

Validate before calling

// Avoid calling from an interrupted thread; clear/honor interrupt status deliberately
if (Thread.currentThread().isInterrupted()) {
    // decide: cancel the call, or clear the flag if interruption is stale
    throw new CancellationException("thread already interrupted before rpc");
}
return directory.list(invocation);

Try / catch

try {
    return directory.list(invocation);
} catch (RpcException e) {
    if (Thread.currentThread().isInterrupted()) {
        // interruption-driven cancellation: do not retry; propagate as cancellation
        throw new CancellationException("rpc interrupted: " + e.getMessage());
    }
    throw e;
}

Prevention

When it happens

Trigger: The RPC-calling thread is interrupted while blocked waiting for the directory read lock — e.g., the RPC timed out at a higher layer and the waiting thread was interrupted, or the application is shutting down and interrupting worker threads.

Common situations: Request timeouts configured shorter than the lock wait; application shutdown interrupting in-flight requests; a servlet/actor framework cancelling the calling thread mid-RPC.

Related errors


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