{"record":{"id":"d9af8561c09a3518","repo":"apache/pulsar","slug":"at-least-one-of-maxnummessages-maxnumbytes-timeo","errorCode":null,"errorMessage":"At least one of maxNumMessages, maxNumBytes, timeout must be specified.","messagePattern":"At least one of maxNumMessages, maxNumBytes, timeout must be specified\\.","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"pulsar-client-api/src/main/java/org/apache/pulsar/client/api/BatchReceivePolicy.java","lineNumber":100,"sourceCode":"     */\n    private final int maxNumBytes;\n\n    /**\n     * timeout for waiting for enough messages(enough number or enough bytes).\n     */\n    private final int timeout;\n    private final TimeUnit timeoutUnit;\n\n\n    /**\n     * If it is false, one time `batchReceive()` only can receive the single topic messages,\n     * the max messages and max size will not be strictly followed. (default: true).\n     */\n    private final boolean messagesFromMultiTopicsEnabled;\n\n    public void verify() {\n        if (maxNumMessages <= 0 && maxNumBytes <= 0 && timeout <= 0) {\n            throw new IllegalArgumentException(\"At least \"\n                    + \"one of maxNumMessages, maxNumBytes, timeout must be specified.\");\n        }\n        if (timeout > 0 && timeoutUnit == null) {\n            throw new IllegalArgumentException(\"Must set timeout unit for timeout.\");\n        }\n    }\n\n    public long getTimeoutMs() {\n        return (timeout > 0 && timeoutUnit != null) ? timeoutUnit.toMillis(timeout) : 0L;\n    }\n\n    public int getMaxNumMessages() {\n        return maxNumMessages;\n    }\n\n    public int getMaxNumBytes() {\n        return maxNumBytes;\n    }","sourceCodeStart":82,"sourceCodeEnd":118,"githubUrl":"https://github.com/apache/pulsar/blob/820761864ed8e2a7d2e52dd9763ad2ae117c1395/pulsar-client-api/src/main/java/org/apache/pulsar/client/api/BatchReceivePolicy.java#L82-L118","documentation":"BatchReceivePolicy.verify() enforces that a batch receive policy is not a no-op: at least one bound among maxNumMessages, maxNumBytes, and timeout must be positive, otherwise the consumer could wait forever without any limit. If all three are <= 0, it throws IllegalArgumentException. This runs when the policy is attached to a ConsumerBuilder.","triggerScenarios":"ConsumerBuilder.batchReceivePolicy(BatchReceivePolicy.builder()...build()) where all limits were left at defaults 0/-1 (e.g. builder with no values), then consumerBuilder.subscribe() is called.","commonSituations":"Programmatically constructing BatchReceivePolicy from config where all values were absent and defaulted to -1/0; accidentally using the default constructor instead of DEFAULT_POLICY; building a policy but forgetting to set any field.","solutions":["Set at least one of maxNumMessages, maxNumBytes, or timeout to a positive value in the builder.","Use BatchReceivePolicy.DEFAULT_POLICY if you want sensible defaults.","Call policy.verify() yourself (try/catch IllegalArgumentException) right after building to fail fast at configuration time."],"exampleFix":"// before\nBatchReceivePolicy policy = BatchReceivePolicy.builder().build();\n// after\nBatchReceivePolicy policy = BatchReceivePolicy.builder()\n    .maxNumMessages(100)\n    .maxNumBytes(10 * 1024 * 1024)\n    .timeout(100, TimeUnit.MILLISECONDS)\n    .build();","handlingStrategy":"validation","validationCode":"BatchReceivePolicy policy = /* built policy */;\nboolean bounded = policy.getMaxNumMessages() > 0\n    || policy.getMaxNumBytes() > 0\n    || policy.getTimeout() > 0;\nif (!bounded) {\n    throw new IllegalArgumentException(\n        \"BatchReceivePolicy needs a positive maxNumMessages, maxNumBytes or timeout\");\n}\npolicy.verify();","typeGuard":null,"tryCatchPattern":"try {\n    policy.verify();\n    consumerBuilder.batchReceivePolicy(policy);\n} catch (IllegalArgumentException e) {\n    log.error(\"Invalid BatchReceivePolicy: {}\", e.getMessage());\n    consumerBuilder.batchReceivePolicy(BatchReceivePolicy.DEFAULT_POLICY);\n}","preventionTips":["Always set at least one limit in the BatchReceivePolicy builder.","Call verify() immediately after building to fail at configuration time.","Use BatchReceivePolicy.DEFAULT_POLICY when in doubt."],"tags":["pulsar","consumer","configuration","illegal-argument"],"backgroundTag":"invalid-policy-configuration","analyzedSha":"820761864ed8e2a7d2e52dd9763ad2ae117c1395","analyzedAt":"2026-09-06T00:14:20.138Z","contentChangedAt":"2026-09-06T00:14:20.138Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}