apache/incubator-seata · error · FrameworkException

Invalid Client ID: {clientId}

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.

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)

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.