{"record":{"id":"654af18a29f26464","repo":"apache/incubator-seata","slug":"register-tm-failed-client-version-s-server-vers","errorCode":null,"errorMessage":"register TM failed. client version: %s,server version: %s, errorMsg: %s, channel: %s","messagePattern":"register TM failed\\. client version: (.+?),server version: (.+?), errorMsg: (.+?), channel: (.+?)","errorType":"exception","errorClass":"FrameworkException","httpStatus":null,"severity":"error","filePath":"core/src/main/java/org/apache/seata/core/rpc/netty/TmNettyRemotingClient.java","lineNumber":261,"sourceCode":"        if (LOGGER.isInfoEnabled()) {\n            LOGGER.info(\n                    \"register TM success. client version:{}, server version:{},channel:{}\",\n                    registerTMRequest.getVersion(),\n                    registerTMResponse.getVersion(),\n                    channel);\n        }\n        getClientChannelManager().registerChannel(serverAddress, channel, registerTMRequest.getVersion());\n    }\n\n    @Override\n    public void onRegisterMsgFail(\n            String serverAddress, Channel channel, Object response, AbstractMessage requestMessage) {\n        RegisterTMRequest registerTMRequest = (RegisterTMRequest) requestMessage;\n        RegisterTMResponse registerTMResponse = (RegisterTMResponse) response;\n        String errMsg = String.format(\n                \"register TM failed. client version: %s,server version: %s, errorMsg: %s, \" + \"channel: %s\",\n                registerTMRequest.getVersion(), registerTMResponse.getVersion(), registerTMResponse.getMsg(), channel);\n        throw new FrameworkException(errMsg);\n    }\n\n    @Override\n    public void destroy() {\n        super.destroy();\n        initialized.getAndSet(false);\n        instance = null;\n    }\n\n    @Override\n    protected Function<String, NettyPoolKey> getPoolKeyFunction() {\n        return severAddress -> {\n            RegisterTMRequest message = new RegisterTMRequest(applicationId, transactionServiceGroup, getExtraData());\n            return new NettyPoolKey(NettyPoolKey.TransactionRole.TMROLE, severAddress, message);\n        };\n    }\n\n    private void registerProcessor() {","sourceCodeStart":243,"sourceCodeEnd":279,"githubUrl":"https://github.com/apache/incubator-seata/blob/e01f97c6db397165050caa6764020410c2c8199a/core/src/main/java/org/apache/seata/core/rpc/netty/TmNettyRemotingClient.java#L243-L279","documentation":"Thrown from TmNettyRemotingClient.onRegisterMsgFail: the Seata Server returned a failure RegisterTMResponse for the transaction-manager registration request. The message captures client/server versions, the server's errorMsg, and the channel, wrapped in FrameworkException. The server explicitly refused the TM registration rather than the channel failing.","triggerScenarios":"TMClient.init(applicationId, transactionServiceGroup) connects and sends RegisterTMRequest; the server responds with a non-success RegisterTMResponse — typically because the transaction service group is unknown to that server or a version/compatibility check failed.","commonSituations":"Client's txServiceGroup is not configured in server's service.vgroupMapping; client pointed at wrong registry namespace/cluster and reached a server that does not host the group; io.seata (1.x) client talking to an org.apache.seata (2.x) server; typo in the group name on either side.","solutions":["Compare the txServiceGroup string on the client against the server's seata.service.vgroupMapping keys (exact match, no typo, same case).","Add/fix the mapping on the server (service.vgroupMapping.my_tx_group=default) and ensure the 'default' cluster is in the registry.","Align client and server Seata versions if the errorMsg hints at version rejection.","Confirm registry namespace/cluster/group on the client matches the server's registration so the TM reaches a server that owns the group."],"exampleFix":"# before\n# client: TMClient.init(\"app\", \"order_tx_group\")\n# server application.yml:\nseata:\n  service:\n    vgroupMapping:\n      order-group: \"default\"   # name mismatch -> register TM failed\n\n# after\nseata:\n  service:\n    vgroupMapping:\n      order_tx_group: \"default\"","handlingStrategy":"validation","validationCode":"// fail fast before TMClient.init if the transaction group resolves to no server\nString group = \"my_tx_group\";\nList<String> servers = io.seata.discovery.registry.RegistryFactory.getInstance().lookup(group);\nif (servers == null || servers.isEmpty()) {\n    throw new IllegalStateException(\"txServiceGroup '\" + group + \"' unknown - add it to server service.vgroupMapping\");\n}\nTMClient.init(applicationId, group);","typeGuard":null,"tryCatchPattern":"try {\n    TMClient.init(applicationId, txServiceGroup);\n} catch (io.seata.common.exception.FrameworkException e) {\n    if (e.getMessage() != null && e.getMessage().contains(\"register TM failed\")) {\n        // server rejected the TM: surface as config error, include server errorMsg from the message\n        throw new IllegalStateException(\"TM registration rejected: \" + e.getMessage(), e);\n    }\n    throw e;\n}","preventionTips":["Single-source the txServiceGroup name between client and server configs (env var / config map).","Add an integration test that boots TMClient against a test server to catch mapping mistakes in CI.","Version-align client/server; check server logs at the first sign of register TM failed."],"tags":["client","tm","registration","transaction-group","configuration"],"backgroundTag":null,"analyzedSha":"e01f97c6db397165050caa6764020410c2c8199a","analyzedAt":"2026-08-14T10:23:53.097Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}