{"record":{"id":"11edae4bbd7578cd","repo":"apache/pulsar","slug":"maxmessages-must-be-0","errorCode":null,"errorMessage":"maxMessages must be >= 0","messagePattern":"maxMessages must be >= 0","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"pulsar-client-api-v5/src/main/java/org/apache/pulsar/client/api/v5/config/BatchingPolicy.java","lineNumber":57,"sourceCode":"    private static final Duration DEFAULT_MAX_PUBLISH_DELAY = Duration.ofMillis(1);\n    private static final int DEFAULT_MAX_MESSAGES = 1000;\n    private static final MemorySize DEFAULT_MAX_SIZE = MemorySize.ofKilobytes(128);\n\n    private static final BatchingPolicy DISABLED =\n            new BatchingPolicy(false, DEFAULT_MAX_PUBLISH_DELAY, DEFAULT_MAX_MESSAGES, DEFAULT_MAX_SIZE);\n\n    private final boolean enabled;\n    private final Duration maxPublishDelay;\n    private final int maxMessages;\n    private final MemorySize maxSize;\n\n    private BatchingPolicy(boolean enabled, Duration maxPublishDelay, int maxMessages, MemorySize maxSize) {\n        if (maxPublishDelay == null) {\n            maxPublishDelay = DEFAULT_MAX_PUBLISH_DELAY;\n        }\n        Objects.requireNonNull(maxSize, \"maxSize must not be null\");\n        if (maxMessages < 0) {\n            throw new IllegalArgumentException(\"maxMessages must be >= 0\");\n        }\n        if (maxSize.bytes() < 0) {\n            throw new IllegalArgumentException(\"maxBytes must be >= 0\");\n        }\n        this.enabled = enabled;\n        this.maxPublishDelay = maxPublishDelay;\n        this.maxMessages = maxMessages;\n        this.maxSize = maxSize;\n    }\n\n    /**\n     * @return whether batching is enabled\n     */\n    public boolean enabled() {\n        return enabled;\n    }\n\n    /**","sourceCodeStart":39,"sourceCodeEnd":75,"githubUrl":"https://github.com/apache/pulsar/blob/820761864ed8e2a7d2e52dd9763ad2ae117c1395/pulsar-client-api-v5/src/main/java/org/apache/pulsar/client/api/v5/config/BatchingPolicy.java#L39-L75","documentation":"The private BatchingPolicy constructor (reached via its builder) requires maxMessages to be non-negative, since it caps how many messages may be accumulated in a single batch. A negative value is nonsensical as a cap, so the library throws IllegalArgumentException at construction time.","triggerScenarios":"Calling BatchingPolicy.builder().maxMessages(n) with n < 0, or invoking the private constructor via a factory with a negative maxMessages argument, e.g. maxMessages(-1).","commonSituations":"Computing the batch size from a formula that can go negative (e.g. remaining quota subtraction); parsing a config value with a stray minus sign; a defaulting routine that uses -1 as a sentinel for 'unset' instead of 0 or Optional.","solutions":["Pass 0 or a positive number to maxMessages; use 0 if you want to disable message-count-based batching.","If -1 is your 'unset' sentinel, map it to the builder default (omit the maxMessages call).","Validate the value at config load time: Math.max(0, configuredValue) or reject the config."],"exampleFix":"// before\nBatchingPolicy bp = BatchingPolicy.builder()\n    .maxMessages(-1) // IllegalArgumentException\n    .build();\n\n// after\nBatchingPolicy bp = BatchingPolicy.builder()\n    .maxMessages(1000) // or omit to use the default\n    .build();","handlingStrategy":"validation","validationCode":"if (maxMessages < 0) {\n    throw new IllegalArgumentException(\"maxMessages must be >= 0, got: \" + maxMessages);\n}\nBatchingPolicy bp = BatchingPolicy.builder().maxMessages(maxMessages).build();","typeGuard":"static boolean isValidMaxMessages(int v) { return v >= 0; }","tryCatchPattern":"try {\n    bp = BatchingPolicy.builder().maxMessages(cfg).build();\n} catch (IllegalArgumentException e) {\n    log.warn(\"Invalid maxMessages, using default batching\", e);\n    bp = BatchingPolicy.builder().build();\n}","preventionTips":["Never use -1 as an 'unset' sentinel; omit the builder call or use Optional instead.","Clamp computed batch sizes with Math.max(0, value).","Check the sign of any value derived from quota/limit arithmetic."],"tags":["java","configuration","illegal-argument","batching","producer"],"backgroundTag":"invalid-configuration-value","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"}