{"record":{"id":"8912164f2c96e887","repo":"alibaba/Sentinel","slug":"bad-request","errorCode":"BAD_REQUEST","errorMessage":"bad request","messagePattern":"bad request","errorType":"exception","errorClass":"SentinelClusterException","httpStatus":null,"severity":"error","filePath":"sentinel-cluster/sentinel-cluster-client-default/src/main/java/com/alibaba/csp/sentinel/cluster/client/NettyTransportClient.java","lineNumber":213,"sourceCode":"        RecordLog.info(\"[NettyTransportClient] Cluster transport client stopped\");\n    }\n\n    private boolean validRequest(Request request) {\n        return request != null && request.getType() >= 0;\n    }\n\n    @Override\n    public boolean isReady() {\n        return channel != null && clientHandler != null && clientHandler.hasStarted();\n    }\n\n    @Override\n    public ClusterResponse sendRequest(ClusterRequest request) throws Exception {\n        if (!isReady()) {\n            throw new SentinelClusterException(ClusterErrorMessages.CLIENT_NOT_READY);\n        }\n        if (!validRequest(request)) {\n            throw new SentinelClusterException(ClusterErrorMessages.BAD_REQUEST);\n        }\n        int xid = getCurrentId();\n        try {\n            request.setId(xid);\n\n            channel.writeAndFlush(request);\n\n            ChannelPromise promise = channel.newPromise();\n            TokenClientPromiseHolder.putPromise(xid, promise);\n\n            if (!promise.await(ClusterClientConfigManager.getRequestTimeout())) {\n                throw new SentinelClusterException(ClusterErrorMessages.REQUEST_TIME_OUT);\n            }\n\n            SimpleEntry<ChannelPromise, ClusterResponse> entry = TokenClientPromiseHolder.getEntry(xid);\n            if (entry == null || entry.getValue() == null) {\n                // Should not go through here.\n                throw new SentinelClusterException(ClusterErrorMessages.UNEXPECTED_STATUS);","sourceCodeStart":195,"sourceCodeEnd":231,"githubUrl":"https://github.com/alibaba/Sentinel/blob/a3f40ba8e900c8489bd520274739f17235a7721c/sentinel-cluster/sentinel-cluster-client-default/src/main/java/com/alibaba/csp/sentinel/cluster/client/NettyTransportClient.java#L195-L231","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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"],"exampleFix":"// before\nclient.sendRequest(null);\n\n// after\nif (request != null && request.getType() >= 0) {\n    client.sendRequest(request);\n}","handlingStrategy":"validation","validationCode":"if (request != null && request.getType() >= 0) {\n    client.sendRequest(request);\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Build requests only through the standard factories with ClusterConstants message types","Never pass null or partially initialized ClusterRequest objects to the transport"],"tags":["cluster","validation","netty","bad-request"],"backgroundTag":null,"analyzedSha":"a3f40ba8e900c8489bd520274739f17235a7721c","analyzedAt":"2026-08-14T11:10:30.678Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}