{"record":{"id":"191f8b7b427c1b8a","repo":"LMAX-Exchange/disruptor","slug":"n-must-be-0-and-buffersize-191f8b","errorCode":null,"errorMessage":"n must be > 0 and < bufferSize","messagePattern":"n must be > 0 and < bufferSize","errorType":"exception","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"src/main/java/com/lmax/disruptor/SingleProducerSequencer.java","lineNumber":140,"sourceCode":"     * @see Sequencer#next()\n     */\n    @Override\n    public long next()\n    {\n        return next(1);\n    }\n\n    /**\n     * @see Sequencer#next(int)\n     */\n    @Override\n    public long next(final int n)\n    {\n        assert sameThread() : \"Accessed by two threads - use ProducerType.MULTI!\";\n\n        if (n < 1 || n > bufferSize)\n        {\n            throw new IllegalArgumentException(\"n must be > 0 and < bufferSize\");\n        }\n\n        long nextValue = this.nextValue;\n\n        long nextSequence = nextValue + n;\n        long wrapPoint = nextSequence - bufferSize;\n        long cachedGatingSequence = this.cachedValue;\n\n        if (wrapPoint > cachedGatingSequence || cachedGatingSequence > nextValue)\n        {\n            cursor.setVolatile(nextValue);  // StoreLoad fence\n\n            long minSequence;\n            while (wrapPoint > (minSequence = Util.getMinimumSequence(gatingSequences, nextValue)))\n            {\n                LockSupport.parkNanos(1L); // TODO: Use waitStrategy to spin?\n            }\n","sourceCodeStart":122,"sourceCodeEnd":158,"githubUrl":"https://github.com/LMAX-Exchange/disruptor/blob/c871ca49826a6be7ada6957f6fbafcfecf7b1f87/src/main/java/com/lmax/disruptor/SingleProducerSequencer.java#L122-L158","documentation":"Thrown by SingleProducerSequencer.next(int n) when n < 1 or n > bufferSize. Identical contract to the multi-producer variant: next(n) claims n slots and blocks until they are free; zero/negative is meaningless and n greater than the ring capacity would self-deadlock. Note this sequencer also asserts single-thread access (an AssertionError 'Accessed by two threads' covers that separate misuse).","triggerScenarios":"Calling next(0), next(-1), or next(bufferSize + 1) on a ring buffer created with ProducerType.SINGLE — commonly next(list.size()) with an empty list or a list bigger than the ring.","commonSituations":"Empty-batch publish path not guarded; batch size configured above ring capacity after a capacity reduction; code shared between single- and multi-producer topologies hitting the single-producer validation first.","solutions":["Guard the caller: skip empty batches, clamp or chunk batches to <= bufferSize.","Increase bufferSize to at least the maximum batch, or split the batch.","Verify you are not accidentally on ProducerType.SINGLE with multiple producer threads (which trips the same-thread assert)."],"exampleFix":"// before\nlong hi = ringBuffer.next(items.size()); // items.size() == 0 or > bufferSize\n\n// after\nif (items.isEmpty()) return;\nlong hi = ringBuffer.next(Math.min(items.size(), ringBuffer.getBufferSize()));","handlingStrategy":"validation","validationCode":"if (n < 1 || n > ringBuffer.getBufferSize()) {\n    throw new IllegalArgumentException(\"claim must be in [1, bufferSize]\");\n}\nlong hi = ringBuffer.next(n);","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Skip empty batches before calling next().","With ProducerType.SINGLE, also ensure exactly one producer thread."],"tags":["disruptor","producer","single-producer","batching","validation"],"backgroundTag":null,"analyzedSha":"c871ca49826a6be7ada6957f6fbafcfecf7b1f87","analyzedAt":"2026-08-14T14:22:36.358Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}