alibaba/nacos · error · NacosException

-401

-401

Error message

Client not connected, current status:{}

What it means

RpcClient.request() throws CLIENT_DISCONNECT (-401) when, at the moment of attempting the call, currentConnection is null or the client status is not RUNNING. The client never reached or has lost its active gRPC connection, so no request can be sent. The call loop will retry up to retryTimes and then surface this error.

Source

Thrown at common/src/main/java/com/alibaba/nacos/common/remote/client/RpcClient.java:671

    
    /**
     * send request.
     *
     * @param request request.
     * @return response from server.
     */
    public Response request(Request request, long timeoutMills) throws NacosException {
        int retryTimes = 0;
        Response response;
        Throwable exceptionThrow = null;
        long start = System.currentTimeMillis();
        while (retryTimes <= rpcClientConfig.retryTimes() && (timeoutMills <= 0
            || System.currentTimeMillis() < timeoutMills + start)) {
            boolean waitReconnect = false;
            try {
                if (this.currentConnection == null || !isRunning()) {
                    waitReconnect = true;
                    throw new NacosException(NacosException.CLIENT_DISCONNECT,
                        "Client not connected, current status:" + rpcClientStatus.get());
                }
                response = this.currentConnection.request(request, timeoutMills);
                if (response == null) {
                    throw new NacosException(SERVER_ERROR, "Unknown Exception.");
                }
                if (response instanceof ErrorResponse) {
                    if (response.getErrorCode() == NacosException.UN_REGISTER) {
                        synchronized (this) {
                            waitReconnect = true;
                            if (rpcClientStatus.compareAndSet(RpcClientStatus.RUNNING,
                                RpcClientStatus.UNHEALTHY)) {
                                LoggerUtils.printIfErrorEnabled(LOGGER,
                                    "Connection is unregistered, switch server, connectionId = {}, request = {}",
                                    currentConnection.getConnectionId(),
                                    request.getClass().getSimpleName());
                                switchServerAsync();
                            }

View on GitHub (pinned to 9b989acdf1)

Solutions

  1. Ensure RpcClient.start() was called and has completed its first successful connect before issuing requests; check isRunning() before calling.
  2. Verify the server list (ServerListFactory) returns reachable Nacos gRPC ports (default 9849) and that firewalls allow them.
  3. Increase rpcClientConfig.retryTimes() and check logs for repeated 'switch server' to allow reconnect windows to complete.
  4. If TLS/auth is enabled, confirm certificate and credential config so the handshake succeeds and the connection enters RUNNING.

Example fix

// before — request issued before the client is connected
RpcClient client = RpcClientFactory.createClient(...);
client.start();
Response r = client.request(req, 3000); // may throw -401

// after — gate on running state
if (!client.isRunning()) {
    // wait or trigger reconnect before requesting
}
Response r = client.request(req, 3000);
Defensive patterns

Strategy: validation

Validate before calling

static Response guardedRequest(RpcClient client, Request req, long timeout) throws NacosException {
    if (!client.isRunning()) {
        throw new NacosException(NacosException.CLIENT_DISCONNECT,
            "Caller aborted: client not RUNNING before request");
    }
    return client.request(req, timeout);
}

Try / catch

try {
    response = client.request(req, timeout);
} catch (NacosException ne) {
    if (ne.getErrCode() == NacosException.CLIENT_DISCONNECT) {
        // wait for reconnect / back off, then retry once
    } else { throw ne; }
}

Prevention

When it happens

Trigger: Calling request() before start() has connected, after the server closed/evicted the connection, during a server switch/reconnect, or when the network is down and the client fell back to UNHEALTHY. Each iteration re-checks `currentConnection == null || !isRunning()` and rethrows before attempting the wire call.

Common situations: Server address wrong/unreachable; server restarted without client reconnect completing; client started but start() not awaited; gRPC port blocked by firewall; credentials/TLS handshake failing so the connection never becomes RUNNING; long GC pause or network partition tripping the health check.

Related errors


AI-assisted analysis of alibaba/nacos@9b989acdf1 (2026-08-14). Data as JSON: /api/errors/c1a742022a142b43. Report an issue: GitHub.