alibaba/Sentinel · error · SentinelClusterException

BAD_REQUEST

BAD_REQUEST

Error message

bad request

What it means

After the readiness check, NettyTransportClient.sendRequest() validates the request via validRequest(): request != null && request.getType() >= 0. Failing that it throws SentinelClusterException(BAD_REQUEST). It indicates a malformed or internally inconsistent ClusterRequest was passed to the transport — almost always a programming/integration bug rather than a network condition.

Source

Thrown at sentinel-cluster/sentinel-cluster-client-default/src/main/java/com/alibaba/csp/sentinel/cluster/client/NettyTransportClient.java:213

        RecordLog.info("[NettyTransportClient] Cluster transport client stopped");
    }

    private boolean validRequest(Request request) {
        return request != null && request.getType() >= 0;
    }

    @Override
    public boolean isReady() {
        return channel != null && clientHandler != null && clientHandler.hasStarted();
    }

    @Override
    public ClusterResponse sendRequest(ClusterRequest request) throws Exception {
        if (!isReady()) {
            throw new SentinelClusterException(ClusterErrorMessages.CLIENT_NOT_READY);
        }
        if (!validRequest(request)) {
            throw new SentinelClusterException(ClusterErrorMessages.BAD_REQUEST);
        }
        int xid = getCurrentId();
        try {
            request.setId(xid);

            channel.writeAndFlush(request);

            ChannelPromise promise = channel.newPromise();
            TokenClientPromiseHolder.putPromise(xid, promise);

            if (!promise.await(ClusterClientConfigManager.getRequestTimeout())) {
                throw new SentinelClusterException(ClusterErrorMessages.REQUEST_TIME_OUT);
            }

            SimpleEntry<ChannelPromise, ClusterResponse> entry = TokenClientPromiseHolder.getEntry(xid);
            if (entry == null || entry.getValue() == null) {
                // Should not go through here.
                throw new SentinelClusterException(ClusterErrorMessages.UNEXPECTED_STATUS);

View on GitHub (pinned to a3f40ba8e9)

Solutions

  1. Ensure requests are built with a valid type constant from ClusterConstants (e.g. ClusterConstants.MSG_TYPE_PING / FLOW_RULE type ids)
  2. Null-check before calling sendRequest; do not send null requests
  3. If extending the client, reuse the provided request factories instead of manual construction

Example fix

// before
client.sendRequest(null);

// after
if (request != null && request.getType() >= 0) {
    client.sendRequest(request);
}
Defensive patterns

Strategy: validation

Validate before calling

if (request != null && request.getType() >= 0) {
    client.sendRequest(request);
}

Prevention

When it happens

Trigger: Passing null to sendRequest; constructing a ClusterRequest with an unset/negative type (e.g. a custom token request type not set from ClusterConstants); reusing a partially built request object.

Common situations: Custom extensions of the cluster client that build requests manually; reflection/serialization paths that leave request type at 0-minus or unset; test harnesses creating dummy requests.

Related errors


AI-assisted analysis of alibaba/Sentinel@a3f40ba8e9 (2026-08-14). Data as JSON: /api/errors/8912164f2c96e887. Report an issue: GitHub.