apache/incubator-seata · error · FrameworkException

Invalid Client ID

Error message

Invalid Client ID: {clientId}

What it means

FrameworkException thrown by ChannelManager.getChannel when the clientId string does not parse into exactly 3 colon-separated parts. Seata encodes a client identity as ApplicationId:IP:Port; anything else (missing segments, wrong separators, extra colons in IPv6 without brackets, null) is rejected before any channel lookup.

Solutions

  1. Pass the clientId exactly as delivered in the RegisterRMRequest (applicationId:ip:port), never reconstruct it
  2. For IPv6, use the bracketed form or verify how the client encoded the address
  3. Log the raw clientId at the boundary and validate it with a 3-part split before calling channel APIs
  4. Upgrade client and server to matching seata versions so id formats agree

Example fix

// before
String clientId = app + ':' + host + ':' + port + ':extra'; // malformed
server.sendSyncRequest(resourceId, clientId, msg, true);

// after
String clientId = app + ':' + host + ':' + port; // ApplicationId:IP:Port
if (clientId.split(":").length != 3) {
    throw new IllegalArgumentException("bad clientId: " + clientId);
}
server.sendSyncRequest(resourceId, clientId, msg, true);
Defensive patterns

Strategy: validation

Validate before calling

static boolean isValidClientId(String clientId) {
    if (clientId == null) return false;
    String[] parts = clientId.split(":");
    return parts.length == 3 && !parts[0].isEmpty() && !parts[1].isEmpty()
        && parts[2].matches("\\d+");
}

Type guard

static boolean isValidClientId(String clientId) {
    return clientId != null && clientId.split(":").length == 3;
}

Try / catch

catch (FrameworkException e) {
    if (e.getMessage() != null && e.getMessage().startsWith("Invalid Client ID")) {
        // reject the request with a 4xx-style error; log the raw id
    }
}

Prevention

When it happens

Trigger: Calling any server API that resolves an RM channel by clientId (e.g. sendSyncRequest(resourceId, clientId, ...)) with a malformed clientId — readClientId returns null or an array whose length != 3.

Common situations: Custom code constructing clientIds by hand; IPv6 addresses containing colons that break naive splitting; clientId truncated or re-encoded through a config/serialization layer; version drift where an old client sends a legacy id format.

Related errors


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

Appendix: source

Thrown at core/src/main/java/org/apache/seata/core/rpc/netty/ChannelManager.java:369

        }
        return null;
    }

    /**
     * Gets get channel.
     *
     * @param resourceId Resource ID
     * @param clientId   Client ID - ApplicationId:IP:Port
     * @param tryOtherApp try other app
     * @return Corresponding channel, NULL if not found.
     */
    public static Channel getChannel(String resourceId, String clientId, boolean tryOtherApp) {
        Channel resultChannel = null;

        String[] clientIdInfo = readClientId(clientId);

        if (clientIdInfo == null || clientIdInfo.length != 3) {
            throw new FrameworkException("Invalid Client ID: " + clientId);
        }

        if (StringUtils.isBlank(resourceId)) {
            if (LOGGER.isInfoEnabled()) {
                LOGGER.info("No channel is available, resourceId is null or empty");
            }
            return null;
        }

        String targetApplicationId = clientIdInfo[0];
        String targetIP = clientIdInfo[1];
        int targetPort = Integer.parseInt(clientIdInfo[2]);

        ConcurrentMap<String, ConcurrentMap<String, ConcurrentMap<Integer, RpcContext>>> applicationIdMap =
                RM_CHANNELS.get(resourceId);

        if (targetApplicationId == null || applicationIdMap == null || applicationIdMap.isEmpty()) {
            if (LOGGER.isInfoEnabled()) {

View on GitHub (pinned to e01f97c6db)