alibaba/nacos · critical · NacosRuntimeException

CLIENT_DISCONNECT

CLIENT_DISCONNECT

Error message

AI client connection already disconnected: ${parentClientId}

What it means

Thrown by CanonicalA2aEndpointOperationService.ensureChildClient when the parent AI gRPC client connection (parentClientId) is no longer present in clientManager at the start of child-client creation. This is a NacosRuntimeException with CLIENT_DISCONNECT code, indicating the originating connection dropped before or during endpoint registration.

Source

Thrown at ai/src/main/java/com/alibaba/nacos/ai/service/a2a/CanonicalA2aEndpointOperationService.java:178

    @Override
    public void clientDisConnected(Connection connect) {
        if (!RemoteConstants.LABEL_MODULE_AI
            .equals(connect.getMetaInfo().getLabel(RemoteConstants.LABEL_MODULE))) {
            return;
        }
        Set<String> children = childClientIds.remove(connect.getMetaInfo().getConnectionId());
        if (children == null) {
            return;
        }
        for (String childClientId : children) {
            clientManager.clientDisconnected(childClientId);
        }
    }
    
    private String ensureChildClient(String parentClientId, String namespaceId, String agentName,
        String version) {
        if (!clientManager.contains(parentClientId)) {
            throw new NacosRuntimeException(NacosException.CLIENT_DISCONNECT,
                "AI client connection already disconnected: " + parentClientId);
        }
        String childClientId = childClientId(parentClientId, namespaceId, agentName, version);
        if (!clientManager.contains(childClientId)) {
            ClientAttributes attributes = new ClientAttributes();
            attributes.addClientAttribute(ClientConstants.CONNECTION_TYPE,
                ClientConstants.DEFAULT_FACTORY);
            clientManager.clientConnected(childClientId, attributes);
        }
        childClientIds.computeIfAbsent(parentClientId,
            key -> ConcurrentHashMap.newKeySet()).add(childClientId);
        if (!clientManager.contains(parentClientId)) {
            disconnectChild(parentClientId, childClientId);
            throw new NacosRuntimeException(NacosException.CLIENT_DISCONNECT,
                "AI client connection already disconnected: " + parentClientId);
        }
        return childClientId;
    }

View on GitHub (pinned to 9b989acdf1)

Solutions

  1. Reconnect the AI gRPC client and obtain the new parentClientId before retrying endpoint registration.
  2. Verify clientManager.contains(parentClientId) is true before calling register.
  3. If the connection is flaky, add retry logic that re-establishes the connection on CLIENT_DISCONNECT.
  4. Check server logs for connection eviction reasons (idle timeout, resource pressure).

Example fix

// before
endpointOpService.register(staleParentClientId, ns, agentName, endpoints);

// after
if (!clientManager.contains(parentClientId)) {
    parentClientId = reconnectAiClient(); // establish new gRPC connection
}
endpointOpService.register(parentClientId, ns, agentName, endpoints);
Defensive patterns

Strategy: validation

Validate before calling

// Verify parent connection is alive before registering
if (!clientManager.contains(parentClientId)) {
    parentClientId = reconnectAiGrpcClient(); // establish new connection
}
endpointOpService.register(parentClientId, ns, agentName, endpoints);

Type guard

public static boolean isParentConnected(ClientManager mgr, String parentClientId) {
    return mgr.contains(parentClientId);
}

Try / catch

try {
    endpointOpService.register(parentClientId, ns, agentName, endpoints);
} catch (NacosRuntimeException e) {
    if (e.getCode() == NacosException.CLIENT_DISCONNECT) {
        parentClientId = reconnectAiGrpcClient();
        endpointOpService.register(parentClientId, ns, agentName, endpoints);
    } else {
        throw e;
    }
}

Prevention

When it happens

Trigger: The AI agent's gRPC connection disconnected (network failure, client shutdown, server-side eviction) before the register call reached ensureChildClient. A deregister or reconnect happened concurrently, removing the parent client from the manager. Stale parentClientId reused after reconnect produced a new connection ID.

Common situations: Network instability causing the gRPC connection to drop mid-operation. Client restart that created a new connection ID while old code path still references the old one. Long-running registration that outlived a connection keepalive timeout. Server-side connection eviction under memory pressure.

Related errors


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