{"record":{"id":"7b87ad5dc08459b9","repo":"apache/incubator-seata","slug":"rm-client-is-not-connected-dbkey-resourceid-cli","errorCode":null,"errorMessage":"rm client is not connected. dbkey:{resourceId},clientId:{clientId}","messagePattern":"rm client is not connected\\. dbkey:(.+?),clientId:(.+?)","errorType":"exception","errorClass":"IOException","httpStatus":null,"severity":"error","filePath":"core/src/main/java/org/apache/seata/core/rpc/netty/AbstractNettyRemotingServer.java","lineNumber":75,"sourceCode":"\n    @Override\n    public void init() {\n        super.init();\n        serverBootstrap.start();\n    }\n\n    public AbstractNettyRemotingServer(ThreadPoolExecutor messageExecutor, NettyServerConfig nettyServerConfig) {\n        super(messageExecutor);\n        serverBootstrap = new NettyServerBootstrap(nettyServerConfig);\n        serverBootstrap.setChannelHandlers(new ServerHandler());\n    }\n\n    @Override\n    public Object sendSyncRequest(String resourceId, String clientId, Object msg, boolean tryOtherApp)\n            throws TimeoutException, IOException {\n        Channel channel = ChannelManager.getChannel(resourceId, clientId, tryOtherApp);\n        if (channel == null) {\n            throw new IOException(\"rm client is not connected. dbkey:\" + resourceId + \",clientId:\" + clientId);\n        }\n        RpcMessage rpcMessage = buildRequestMessage(msg, ProtocolConstants.MSGTYPE_RESQUEST_SYNC);\n        return super.sendSync(channel, rpcMessage, NettyServerConfig.getRpcRequestTimeout());\n    }\n\n    @Override\n    public Object sendSyncRequest(Channel channel, Object msg) throws TimeoutException, IOException {\n        if (channel == null) {\n            throw new IOException(\"client is not connected\");\n        }\n        RpcMessage rpcMessage = buildRequestMessage(msg, ProtocolConstants.MSGTYPE_RESQUEST_SYNC);\n        return super.sendSync(channel, rpcMessage, NettyServerConfig.getRpcRequestTimeout());\n    }\n\n    @Override\n    public void sendAsyncRequest(Channel channel, Object msg) throws IOException {\n        if (channel == null) {\n            throw new IOException(\"client is not connected\");","sourceCodeStart":57,"sourceCodeEnd":93,"githubUrl":"https://github.com/apache/incubator-seata/blob/e01f97c6db397165050caa6764020410c2c8199a/core/src/main/java/org/apache/seata/core/rpc/netty/AbstractNettyRemotingServer.java#L57-L93","documentation":"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.","triggerScenarios":"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).","commonSituations":"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.","solutions":["Check whether the RM application (the microservice holding that datasource) is alive and connected to the TC","Ensure the RM stays alive until global transactions involving its branches complete (or enable async commit / proper timeout handling on the TC)","Verify the RM's application.id and clientId are stable across restarts so tryOtherApp matching works","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"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"Channel ch = ChannelManager.getChannel(resourceId, clientId, true);\nif (ch == null || !ch.isActive()) {\n    // RM offline: do not call sendSyncRequest(resourceId, clientId, ...)\n}","typeGuard":null,"tryCatchPattern":"catch (IOException e) {\n    if (e.getMessage() != null && e.getMessage().startsWith(\"rm client is not connected\")) {\n        // mark branch as retryable / trigger transaction timeout handling\n    }\n}","preventionTips":["Keep RMs running until global transactions touching their branches finish","Monitor TC->RM connectivity; alert on repeated offline RMs with open branches","Clean undolog on RM databases after forced restarts"],"tags":["server","rm-disconnected","branch","netty"],"backgroundTag":null,"analyzedSha":"e01f97c6db397165050caa6764020410c2c8199a","analyzedAt":"2026-08-14T10:23:53.097Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}