LMAX-Exchange/disruptor · error · IllegalArgumentException

The ring buffer cannot accommodate {} it only has space for

Error message

The ring buffer cannot accommodate {} it only has space for {} entities.

What it means

Thrown by RingBuffer.checkBatchSizing during batch publishing when batchSize exceeds the ring buffer capacity. A batch publish claims batchSize consecutive slots; claiming more slots than the ring holds can never succeed (the publisher would have to wait for itself), so it is rejected up front instead of deadlocking.

Source

Thrown at src/main/java/com/lmax/disruptor/RingBuffer.java:908

    {
        return sequencer.remainingCapacity();
    }

    private void checkBounds(final EventTranslator<E>[] translators, final int batchStartsAt, final int batchSize)
    {
        checkBatchSizing(batchStartsAt, batchSize);
        batchOverRuns(translators, batchStartsAt, batchSize);
    }

    private void checkBatchSizing(final int batchStartsAt, final int batchSize)
    {
        if (batchStartsAt < 0 || batchSize < 0)
        {
            throw new IllegalArgumentException("Both batchStartsAt and batchSize must be positive but got: batchStartsAt " + batchStartsAt + " and batchSize " + batchSize);
        }
        else if (batchSize > bufferSize)
        {
            throw new IllegalArgumentException("The ring buffer cannot accommodate " + batchSize + " it only has space for " + bufferSize + " entities.");
        }
    }

    private <A> void checkBounds(final A[] arg0, final int batchStartsAt, final int batchSize)
    {
        checkBatchSizing(batchStartsAt, batchSize);
        batchOverRuns(arg0, batchStartsAt, batchSize);
    }

    private <A, B> void checkBounds(final A[] arg0, final B[] arg1, final int batchStartsAt, final int batchSize)
    {
        checkBatchSizing(batchStartsAt, batchSize);
        batchOverRuns(arg0, batchStartsAt, batchSize);
        batchOverRuns(arg1, batchStartsAt, batchSize);
    }

    private <A, B, C> void checkBounds(
        final A[] arg0, final B[] arg1, final C[] arg2, final int batchStartsAt, final int batchSize)

View on GitHub (pinned to c871ca4982)

Solutions

  1. Split the batch into chunks of at most ringBuffer.getBufferSize() and publish each chunk.
  2. Or increase the ring buffer size to at least the maximum batch size.
  3. Add a startup check: maxBatchSize <= ringBufferSize.

Example fix

// before
ringBuffer.publishEvents(translators, 0, translators.length); // 5000 into 1024 ring

// after
int chunk = ringBuffer.getBufferSize();
for (int i = 0; i < translators.length; i += chunk) {
    int n = Math.min(chunk, translators.length - i);
    ringBuffer.publishEvents(translators, i, n);
}
Defensive patterns

Strategy: validation

Validate before calling

int capacity = ringBuffer.getBufferSize();
if (batchSize > capacity) {
    for (int i = 0; i < items.size(); i += capacity) {
        ringBuffer.publishEvents(translators, i, Math.min(capacity, items.size() - i));
    }
    return;
}

Prevention

When it happens

Trigger: Calling publishEvents(translators, 0, 5000) on a 1024-entry ring buffer; any batch publish whose count argument is greater than ringBuffer.getBufferSize().

Common situations: Batch size from config outgrows a small ring (e.g. tests use bufferSize 8 while production batches are 100); bulk-loading code that publishes an entire list in one call; capacity tuned down for memory without revisiting batch size.

Related errors


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