apache/incubator-seata · error · FrameworkException
register msg is null, role:%s
Error message
register msg is null, role:%s
What it means
FrameworkException from NettyPoolableFactory.makeObject: the pooled-channel key carried no register message. When the client borrows a channel from the pool, the pool key must contain the RegisterTMRequest/RegisterRMRequest that is sent immediately after connect; a null message means the key was built without its register request, which is an internal invariant violation rather than a network problem.
Source
Thrown at core/src/main/java/org/apache/seata/core/rpc/netty/NettyPoolableFactory.java:63
* @param rpcRemotingClient the rpc remoting client
*/
public NettyPoolableFactory(AbstractNettyRemotingClient rpcRemotingClient, NettyClientBootstrap clientBootstrap) {
this.rpcRemotingClient = rpcRemotingClient;
this.clientBootstrap = clientBootstrap;
}
@Override
public Channel makeObject(NettyPoolKey key) {
InetSocketAddress address = NetUtil.toInetSocketAddress(key.getAddress());
if (LOGGER.isInfoEnabled()) {
LOGGER.info("NettyPool create channel to " + key);
}
Channel tmpChannel = clientBootstrap.getNewChannel(address);
long start = System.currentTimeMillis();
Object response;
Channel channelToServer = null;
if (key.getMessage() == null) {
throw new FrameworkException(
"register msg is null, role:" + key.getTransactionRole().name());
}
try {
response = rpcRemotingClient.sendSyncRequest(tmpChannel, key.getMessage());
if (!isRegisterSuccess(response, key.getTransactionRole())) {
rpcRemotingClient.onRegisterMsgFail(key.getAddress(), tmpChannel, response, key.getMessage());
} else {
channelToServer = tmpChannel;
rpcRemotingClient.onRegisterMsgSuccess(key.getAddress(), tmpChannel, response, key.getMessage());
}
} catch (Exception exx) {
if (tmpChannel != null) {
tmpChannel.close();
}
throw new FrameworkException(
"register " + key.getTransactionRole().name() + " error, errMsg:" + exx.getMessage());
}
if (LOGGER.isInfoEnabled()) {View on GitHub (pinned to e01f97c6db)
Solutions
- Do not construct NettyPoolKey without the register request: use the client's built-in poolKeyFunction (AbstractNettyRemotingClient builds it with RegisterRMRequest/RegisterTMRequest)
- If subclassing, ensure getPoolKeyFunction supplies the register message for every address
- Upgrade to a coherent seata version across all modules — mixed versions can break internal key contracts
- As a workaround, restart the client so keys are rebuilt with their register messages
Defensive patterns
Strategy: try-catch
Validate before calling
NettyPoolKey key = poolKeyFunction.apply(address);
if (key == null || key.getMessage() == null) {
throw new IllegalStateException("pool key missing register message for " + address);
} Type guard
boolean poolKeyHasRegisterMsg(NettyPoolKey key) {
return key != null && key.getMessage() != null;
} Try / catch
catch (FrameworkException e) {
if (e.getMessage().startsWith("register msg is null")) {
// internal misconfiguration: rebuild keys via built-in poolKeyFunction; restart client
}
} Prevention
- Use the stock pool key factories; do not construct NettyPoolKey without a register request
- Keep all seata modules on one version
- Restart the client to rebuild keys if seen after partial upgrades
When it happens
Trigger: poolKeyFunction.apply(address) returning a NettyPoolKey whose message field is null when the pool creates the object — e.g. a custom or misconfigured client bootstrap path that constructs keys without the register request, or internal state where the register message was not yet initialized when reconnect kicked in.
Common situations: Rare in stock deployments; seen with custom client subclasses/forks that override the pool key factory; races during very early startup where reconnect fires before the register message is prepared; version skew in internal APIs after partial upgrades.
Related errors
- can not register RM,err:%s
- register %s error, errMsg:%s
- register RM failed. client version: %s,server version: %s, e
- register TM failed. client version: %s,server version: %s, e
- The default branch type must be AT or XA. the value of the a
AI-assisted analysis of apache/incubator-seata@e01f97c6db (2026-08-14).
Data as JSON: /api/errors/fee5bac226dfafb4.
Report an issue: GitHub.