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
- Ensure requests are built with a valid type constant from ClusterConstants (e.g. ClusterConstants.MSG_TYPE_PING / FLOW_RULE type ids)
- Null-check before calling sendRequest; do not send null requests
- 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
- Build requests only through the standard factories with ClusterConstants message types
- Never pass null or partially initialized ClusterRequest objects to the transport
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.