{"record":{"id":"4ed0915117ac5564","repo":"apache/rocketmq","slug":"long-polling-mode-the-consumer-consumertimeoutmil","errorCode":null,"errorMessage":"Long polling mode, the consumer consumerTimeoutMillisWhenSuspend must greater than brokerSuspendMaxTimeMillis","messagePattern":"Long polling mode, the consumer consumerTimeoutMillisWhenSuspend must greater than brokerSuspendMaxTimeMillis","errorType":"exception","errorClass":"MQClientException","httpStatus":null,"severity":"error","filePath":"client/src/main/java/org/apache/rocketmq/client/impl/consumer/DefaultLitePullConsumerImpl.java","lineNumber":444,"sourceCode":"\n        // Check messageModel is not null.\n        if (null == this.defaultLitePullConsumer.getMessageModel()) {\n            throw new MQClientException(\n                \"messageModel is null\"\n                    + FAQUrl.suggestTodo(FAQUrl.CLIENT_PARAMETER_CHECK_URL),\n                null);\n        }\n\n        // Check allocateMessageQueueStrategy is not null\n        if (null == this.defaultLitePullConsumer.getAllocateMessageQueueStrategy()) {\n            throw new MQClientException(\n                \"allocateMessageQueueStrategy is null\"\n                    + FAQUrl.suggestTodo(FAQUrl.CLIENT_PARAMETER_CHECK_URL),\n                null);\n        }\n\n        if (this.defaultLitePullConsumer.getConsumerTimeoutMillisWhenSuspend() < this.defaultLitePullConsumer.getBrokerSuspendMaxTimeMillis()) {\n            throw new MQClientException(\n                \"Long polling mode, the consumer consumerTimeoutMillisWhenSuspend must greater than brokerSuspendMaxTimeMillis\"\n                    + FAQUrl.suggestTodo(FAQUrl.CLIENT_PARAMETER_CHECK_URL),\n                null);\n        }\n    }\n\n    public PullAPIWrapper getPullAPIWrapper() {\n        return pullAPIWrapper;\n    }\n\n    private void startPullTask(Collection<MessageQueue> mqSet) {\n        for (MessageQueue messageQueue : mqSet) {\n            if (!this.taskTable.containsKey(messageQueue)) {\n                PullTaskImpl pullTask = new PullTaskImpl(messageQueue);\n                this.taskTable.put(messageQueue, pullTask);\n                this.scheduledThreadPoolExecutor.schedule(pullTask, 0, TimeUnit.MILLISECONDS);\n            }\n        }","sourceCodeStart":426,"sourceCodeEnd":462,"githubUrl":"https://github.com/apache/rocketmq/blob/293f5885719fc4aa3619446a1900f58ccfcfdd29/client/src/main/java/org/apache/rocketmq/client/impl/consumer/DefaultLitePullConsumerImpl.java#L426-L462","documentation":"MQClientException from DefaultLitePullConsumerImpl.checkConfig: in long-polling (lite-pull) mode the consumer must be willing to wait longer than the broker is allowed to suspend the connection — consumerTimeoutMillisWhenSuspend must be >= brokerSuspendMaxTimeMillis. If configured otherwise, the broker could legally hold a poll longer than the consumer waits, so start() rejects the combination.","triggerScenarios":"Setting consumerTimeoutMillisWhenSuspend below brokerSuspendMaxTimeMillis (defaults: 15s vs 20s already violates; typical custom breakage: brokerSuspendMaxTimeMillis=30s with default 15s consumer timeout, or consumer timeout lowered to 10s).","commonSituations":"Tuning timeouts to cut latency without understanding the pairing; increasing brokerSuspendMaxTimeMillis to reduce empty-poll traffic while forgetting the consumer side; copying timeout values between push and lite-pull consumers where semantics differ.","solutions":["Keep consumerTimeoutMillisWhenSuspend at least a few seconds above brokerSuspendMaxTimeMillis (e.g. broker 20s -> consumer 25s+)","Or lower brokerSuspendMaxTimeMillis if shorter server-side suspension is acceptable","Revert both to defaults if the tuning was speculative","Document the invariant next to any timeout config in your codebase"],"exampleFix":"// before\nconsumer.setBrokerSuspendMaxTimeMillis(30_000); // raised, consumer timeout still 15s\nconsumer.start(); // violates invariant\n\n// after\nconsumer.setBrokerSuspendMaxTimeMillis(30_000);\nconsumer.setConsumerTimeoutMillisWhenSuspend(35_000);\nconsumer.start();","handlingStrategy":"validation","validationCode":"if (consumer.getConsumerTimeoutMillisWhenSuspend() < consumer.getBrokerSuspendMaxTimeMillis()) {\n    consumer.setConsumerTimeoutMillisWhenSuspend(consumer.getBrokerSuspendMaxTimeMillis() + 5_000L);\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Change suspend timeouts as a pair, never independently","Keep consumer timeout > broker suspend by a safety margin (5s+)","Revert to defaults unless long-poll tuning is deliberate"],"tags":["rocketmq","config","consumer","lite-pull","timeout","long-polling"],"backgroundTag":null,"analyzedSha":"293f5885719fc4aa3619446a1900f58ccfcfdd29","analyzedAt":"2026-08-14T11:50:13.822Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}