LMAX-Exchange/disruptor · error · IllegalArgumentException
n must be > 0 and < bufferSize
Error message
n must be > 0 and < bufferSize
What it means
Thrown by MultiProducerSequencer.next(int n) when n < 1 or n > bufferSize. next(n) claims n sequential slots in one call; claiming zero or negative slots is meaningless, and claiming more than the whole ring at once would deadlock because publishers can never wrap past themselves.
Source
Thrown at src/main/java/com/lmax/disruptor/MultiProducerSequencer.java:116
/**
* @see Sequencer#next()
*/
@Override
public long next()
{
return next(1);
}
/**
* @see Sequencer#next(int)
*/
@Override
public long next(final int n)
{
if (n < 1 || n > bufferSize)
{
throw new IllegalArgumentException("n must be > 0 and < bufferSize");
}
long current = cursor.getAndAdd(n);
long nextSequence = current + n;
long wrapPoint = nextSequence - bufferSize;
long cachedGatingSequence = gatingSequenceCache.get();
if (wrapPoint > cachedGatingSequence || cachedGatingSequence > current)
{
long gatingSequence;
while (wrapPoint > (gatingSequence = Util.getMinimumSequence(gatingSequences, current)))
{
LockSupport.parkNanos(1L); // TODO, should we spin based on the wait strategy?
}
gatingSequenceCache.set(gatingSequence);
}View on GitHub (pinned to c871ca4982)
Solutions
- Guard the caller: skip publishing when the batch is empty, and clamp/split batches so n <= bufferSize.
- If batches can exceed the ring, raise bufferSize to at least the max batch, or chunk the batch into multiple next/publish cycles of at most bufferSize.
- Add an assert/log for computed batch sizes to catch underflow early.
Example fix
// before long hi = ringBuffer.next(items.size()); // items may be empty or > bufferSize // after if (items.isEmpty()) return; int n = Math.min(items.size(), ringBuffer.getBufferSize()); long hi = ringBuffer.next(n);
Defensive patterns
Strategy: validation
Validate before calling
if (n < 1 || n > ringBuffer.getBufferSize()) {
throw new IllegalArgumentException("batch claim n must be in [1, " + ringBuffer.getBufferSize() + "]");
}
long hi = ringBuffer.next(n); Prevention
- Guard every next(items.size()) with an isEmpty() check.
- Keep max batch size <= ring buffer size as an enforced invariant at startup.
When it happens
Trigger: Calling ringBuffer.next(0), ringBuffer.next(n) with n negative, or next(bufferSize + 1) — commonly next(someList.size()) where the list is empty or larger than the ring; also publishing batches via publish(start, size) with a bad size internally routing through next(n).
Common situations: Batch-publishing code that does next(items.size()) without checking for an empty list; a batch size configured larger than the ring buffer capacity (e.g. 8192-item batches into a 4096 ring); a size field that underflows to negative.
Related errors
- n must be > 0
- Both batchStartsAt and batchSize must be positive but got: b
- n must be > 0 and < bufferSize
- n must be > 0
- bufferSize must not be less than 1
AI-assisted analysis of LMAX-Exchange/disruptor@c871ca4982 (2026-08-14).
Data as JSON: /api/errors/ce8662846a1db732.
Report an issue: GitHub.