apache/incubator-seata · error · IOException

rm client is not connected. dbkey:{resourceId},clientId:{cli

Error message

rm client is not connected. dbkey:{resourceId},clientId:{clientId}

What it means

Server-side error: AbstractNettyRemotingServer.sendSyncRequest(resourceId, clientId, msg, tryOtherApp) could not find a live channel to the RM client for the given resource (dataSource proxy) and clientId. The TC keeps channels indexed by resourceId + clientId (ApplicationId:IP:Port); a miss means the RM that owns that branch is not currently connected.

Source

Thrown at core/src/main/java/org/apache/seata/core/rpc/netty/AbstractNettyRemotingServer.java:75

    @Override
    public void init() {
        super.init();
        serverBootstrap.start();
    }

    public AbstractNettyRemotingServer(ThreadPoolExecutor messageExecutor, NettyServerConfig nettyServerConfig) {
        super(messageExecutor);
        serverBootstrap = new NettyServerBootstrap(nettyServerConfig);
        serverBootstrap.setChannelHandlers(new ServerHandler());
    }

    @Override
    public Object sendSyncRequest(String resourceId, String clientId, Object msg, boolean tryOtherApp)
            throws TimeoutException, IOException {
        Channel channel = ChannelManager.getChannel(resourceId, clientId, tryOtherApp);
        if (channel == null) {
            throw new IOException("rm client is not connected. dbkey:" + resourceId + ",clientId:" + clientId);
        }
        RpcMessage rpcMessage = buildRequestMessage(msg, ProtocolConstants.MSGTYPE_RESQUEST_SYNC);
        return super.sendSync(channel, rpcMessage, NettyServerConfig.getRpcRequestTimeout());
    }

    @Override
    public Object sendSyncRequest(Channel channel, Object msg) throws TimeoutException, IOException {
        if (channel == null) {
            throw new IOException("client is not connected");
        }
        RpcMessage rpcMessage = buildRequestMessage(msg, ProtocolConstants.MSGTYPE_RESQUEST_SYNC);
        return super.sendSync(channel, rpcMessage, NettyServerConfig.getRpcRequestTimeout());
    }

    @Override
    public void sendAsyncRequest(Channel channel, Object msg) throws IOException {
        if (channel == null) {
            throw new IOException("client is not connected");

View on GitHub (pinned to e01f97c6db)

Solutions

  1. Check whether the RM application (the microservice holding that datasource) is alive and connected to the TC
  2. Ensure the RM stays alive until global transactions involving its branches complete (or enable async commit / proper timeout handling on the TC)
  3. Verify the RM's application.id and clientId are stable across restarts so tryOtherApp matching works
  4. If the RM was restarted, the branch is orphaned: let the transaction retry/timeout, and inspect undolog on the RM DB for leftover records to clean
Defensive patterns

Strategy: try-catch

Validate before calling

Channel ch = ChannelManager.getChannel(resourceId, clientId, true);
if (ch == null || !ch.isActive()) {
    // RM offline: do not call sendSyncRequest(resourceId, clientId, ...)
}

Try / catch

catch (IOException e) {
    if (e.getMessage() != null && e.getMessage().startsWith("rm client is not connected")) {
        // mark branch as retryable / trigger transaction timeout handling
    }
}

Prevention

When it happens

Trigger: TC initiating a synchronous request to an RM (branch commit/rollback, undo log delete, lock check) when ChannelManager.getChannel(resourceId, clientId, tryOtherApp) returns null: RM disconnected, or the resource/clientId pair never registered (or tryOtherApp found no alternate app either).

Common situations: RM application restarted or crashed while a global transaction was still in flight; RM registered with a different applicationId so tryOtherApp cannot match; network partition between TC and RM; RM unregistered its resource while branches were pending.

Related errors


AI-assisted analysis of apache/incubator-seata@e01f97c6db (2026-08-14). Data as JSON: /api/errors/7b87ad5dc08459b9. Report an issue: GitHub.