LMAX-Exchange/disruptor · error · IllegalArgumentException

bufferSize must be a power of 2

Error message

bufferSize must be a power of 2

What it means

Thrown by the AbstractSequencer constructor when the buffer size is not a power of 2 (Integer.bitCount(bufferSize) != 1). Disruptor uses bitmask arithmetic (sequence & indexMask) instead of modulo to index into the ring buffer, which only works when the capacity is exactly 1, 2, 4, 8, 16, ... entries.

Solutions

  1. Change the buffer size to the nearest power of 2 (e.g. 1000 -> 1024, 3000 -> 4096).
  2. If the size is dynamic, round up: int size = Integer.highestOneBit(desired - 1) << 1;
  3. Add a startup assertion/util check so misconfiguration is caught with a clearer message.

Example fix

// before
RingBuffer<Event> rb = RingBuffer.createMultiProducer(Event::new, 1000);

// after
RingBuffer<Event> rb = RingBuffer.createMultiProducer(Event::new, 1024);
Defensive patterns

Strategy: validation

Validate before calling

static int ceilPow2(int desired) {
    return Integer.highestOneBit(Math.max(1, desired - 1)) << 1;
}
// use: ceilPow2(1000) == 1024

Prevention

When it happens

Trigger: Calling new Disruptor<>(factory, 1000, threadFactory) or RingBuffer.createMultiProducer(factory, 1000) — any size whose binary representation has more than one bit set. Also triggered by sizes like 0-adjacent odd values after fixing error 0.

Common situations: Developer picks a 'round decimal' size (100, 1000, 3000) out of habit; size computed dynamically (e.g. throughput target * multiplier) without rounding up to a power of 2; porting code from another queue library that allowed arbitrary capacities.

Related errors


AI-assisted analysis of LMAX-Exchange/disruptor@c871ca4982 (2026-08-14). Data as JSON: /api/errors/33d464e24fe55bc1. Report an issue: GitHub.

Appendix: source

Thrown at src/main/java/com/lmax/disruptor/AbstractSequencer.java:52

    protected final WaitStrategy waitStrategy;
    protected final Sequence cursor = new Sequence(Sequencer.INITIAL_CURSOR_VALUE);
    protected volatile Sequence[] gatingSequences = new Sequence[0];

    /**
     * Create with the specified buffer size and wait strategy.
     *
     * @param bufferSize   The total number of entries, must be a positive power of 2.
     * @param waitStrategy The wait strategy used by this sequencer
     */
    public AbstractSequencer(final int bufferSize, final WaitStrategy waitStrategy)
    {
        if (bufferSize < 1)
        {
            throw new IllegalArgumentException("bufferSize must not be less than 1");
        }
        if (Integer.bitCount(bufferSize) != 1)
        {
            throw new IllegalArgumentException("bufferSize must be a power of 2");
        }

        this.bufferSize = bufferSize;
        this.waitStrategy = waitStrategy;
    }

    /**
     * @see Sequencer#getCursor()
     */
    @Override
    public final long getCursor()
    {
        return cursor.get();
    }

    /**
     * @see Sequencer#getBufferSize()
     */

View on GitHub (pinned to c871ca4982)