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
- Ensure RpcClient.start() was called and has completed its first successful connect before issuing requests; check isRunning() before calling.
- Verify the server list (ServerListFactory) returns reachable Nacos gRPC ports (default 9849) and that firewalls allow them.
- Increase rpcClientConfig.retryTimes() and check logs for repeated 'switch server' to allow reconnect windows to complete.
- 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
- Always gate requests on client.isRunning().
- Register a ConnectionEventListener to drive reconnect-aware retry instead of blind polling.
- Verify the server gRPC endpoint is reachable before starting the client.
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
- Failed to acquire lock: {}
- -401
- request timeout after {timeout} milliseconds, requestId={req
- SERVER_ERROR
- {e.getErrCode()}
AI-assisted analysis of alibaba/nacos@9b989acdf1 (2026-08-14).
Data as JSON: /api/errors/c1a742022a142b43.
Report an issue: GitHub.