LMAX-Exchange/disruptor · error · IllegalArgumentException

bufferSize must not be less than 1

Error message

bufferSize must not be less than 1

What it means

Thrown by the AbstractSequencer constructor when the ring buffer size passed to a Disruptor/RingBuffer is less than 1. Disruptor requires a strictly positive capacity because the ring buffer is an array-backed circular buffer; a zero or negative size cannot hold any entries. This is a fail-fast configuration error raised before any resource is allocated.

Source

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

    private static final AtomicReferenceFieldUpdater<AbstractSequencer, Sequence[]> SEQUENCE_UPDATER =
        AtomicReferenceFieldUpdater.newUpdater(AbstractSequencer.class, Sequence[].class, "gatingSequences");

    protected final int bufferSize;
    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();
    }

View on GitHub (pinned to c871ca4982)

Solutions

  1. Check the value passed as bufferSize and ensure it is >= 1 before constructing the Disruptor.
  2. If the size comes from configuration, validate it at startup and fail with a clear message naming the property.
  3. Choose a power-of-2 size (e.g. 1024, 4096) so you also satisfy the power-of-2 check that runs immediately after this one.

Example fix

// before
Disruptor<Event> d = new Disruptor<>(Event::new, config.getBufferSize(), threadFactory); // getBufferSize() returns 0

// after
int size = config.getBufferSize();
if (size < 1) throw new IllegalArgumentException("config.bufferSize must be >= 1, got " + size);
Disruptor<Event> d = new Disruptor<>(Event::new, size, threadFactory);
Defensive patterns

Strategy: validation

Validate before calling

int size = config.getBufferSize();
if (size < 1) throw new IllegalArgumentException("bufferSize must be >= 1, got " + size);

Prevention

When it happens

Trigger: Constructing a Disruptor or RingBuffer with bufferSize <= 0, e.g. new Disruptor<>(factory, 0, threadFactory), or creating a sequencer directly (new MultiProducerSequencer(0, waitStrategy)). Typically happens when the size is computed from configuration, a system property, or an expression that evaluates to 0 (e.g. uninitialised int field, empty list size, integer underflow).

Common situations: Size read from a config file/env var that is missing and defaults to 0; capacity derived from partition count or thread count that is 0 in a test environment; off-by-one math producing a negative value; refactoring that moved buffer creation before the size is initialised.

Related errors


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