apache/incubator-seata · error · FrameworkException

can not register RM,err:%s

Error message

can not register RM,err:%s

What it means

FrameworkException from NettyClientChannelManager.acquireChannel: borrowing a channel from the Netty channel pool failed, which in Seata means the connect plus TM/RM register handshake inside NettyPoolableFactory.makeObject threw. The message appends the underlying cause's message; the code above also logs it with the RegisterRM error code.

Source

Thrown at core/src/main/java/org/apache/seata/core/rpc/netty/NettyClientChannelManager.java:353

        if (removed && LOGGER.isInfoEnabled()) {
            LOGGER.info("Cleaned up channel metadata for disconnected address: {}", serverAddress);
        }
    }

    private Channel doConnect(String serverAddress) {
        Channel channelToServer = channels.get(serverAddress);
        if (channelToServer != null && channelToServer.isActive()) {
            return channelToServer;
        }
        Channel channelFromPool;
        try {
            NettyPoolKey currentPoolKey = poolKeyFunction.apply(serverAddress);
            poolKeyMap.put(serverAddress, currentPoolKey);
            channelFromPool = nettyClientKeyPool.borrowObject(currentPoolKey);
            channels.put(serverAddress, channelFromPool);
        } catch (Exception exx) {
            LOGGER.error("{} register RM failed.", FrameworkErrorCode.RegisterRM.getErrCode(), exx);
            throw new FrameworkException("can not register RM,err:" + exx.getMessage());
        }
        return channelFromPool;
    }

    private List<String> getAvailServerList(String transactionServiceGroup) throws Exception {
        List<InetSocketAddress> availInetSocketAddressList =
                RegistryFactory.getInstance().lookup(transactionServiceGroup);
        if (CollectionUtils.isEmpty(availInetSocketAddressList)) {
            return Collections.emptyList();
        }

        return availInetSocketAddressList.stream().map(NetUtil::toStringAddress).collect(Collectors.toList());
    }

    private Channel getExistAliveChannel(Channel rmChannel, String serverAddress) {
        if (rmChannel.isActive()) {
            return rmChannel;
        } else {

View on GitHub (pinned to e01f97c6db)

Solutions

  1. Check the preceding 'register RM failed' log entry and its cause — it names the real failure
  2. Confirm seata-server is running and accepting registrations; test with a fresh client start
  3. Align auth config: if the server requires username/password, set them on the client
  4. Align client/server versions and retry the business operation after the client reconnects

Example fix

# application.yml — server has auth enabled
seata:
  client:
    tm:
      username: seata
      password: seata
    rm:
      username: seata
      password: seata
Defensive patterns

Strategy: retry

Validate before calling

// before RM operations, confirm a live channel exists
Channel ch = channelManager.acquireChannel(serverAddress); // throws with cause if register fails

Try / catch

catch (FrameworkException e) {
    if (e.getMessage().startsWith("can not register RM")) {
        // inspect cause: auth/timeout/unreachable; fix and let background reconnect re-register
    }
}

Prevention

When it happens

Trigger: Calling an RM API (branch register, lock queries, SQL undo operations) that needs a server channel while pool.borrowObject fails: server unreachable, register request rejected/timed out, or the pool's register validation (isRegisterSuccess) failed and onRegisterMsgFail threw.

Common situations: seata-server restarted and the client's cached pool keys are stale; registration rejected due to authentication (server enabled auth, client missing username/password); version-incompatible register responses; brief outage during the first business SQL after startup.

Related errors


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