{"record":{"id":"d0c590df9bd4d96c","repo":"LMAX-Exchange/disruptor","slug":"buffersize-must-not-be-less-than-1-d0c590","errorCode":null,"errorMessage":"bufferSize must not be less than 1","messagePattern":"bufferSize must not be less than 1","errorType":"exception","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"src/main/java/com/lmax/disruptor/RingBuffer.java","lineNumber":52,"sourceCode":"{\n    private static final int BUFFER_PAD = 32;\n\n    private final long indexMask;\n    private final E[] entries;\n    protected final int bufferSize;\n    protected final Sequencer sequencer;\n\n    @SuppressWarnings(\"unchecked\")\n    RingBufferFields(\n        final EventFactory<E> eventFactory,\n        final Sequencer sequencer)\n    {\n        this.sequencer = sequencer;\n        this.bufferSize = sequencer.getBufferSize();\n\n        if (bufferSize < 1)\n        {\n            throw new IllegalArgumentException(\"bufferSize must not be less than 1\");\n        }\n        if (Integer.bitCount(bufferSize) != 1)\n        {\n            throw new IllegalArgumentException(\"bufferSize must be a power of 2\");\n        }\n\n        this.indexMask = bufferSize - 1;\n        this.entries = (E[]) new Object[bufferSize + 2 * BUFFER_PAD];\n        fill(eventFactory);\n    }\n\n    private void fill(final EventFactory<E> eventFactory)\n    {\n        for (int i = 0; i < bufferSize; i++)\n        {\n            entries[BUFFER_PAD + i] = eventFactory.newInstance();\n        }\n    }","sourceCodeStart":34,"sourceCodeEnd":70,"githubUrl":"https://github.com/LMAX-Exchange/disruptor/blob/c871ca49826a6be7ada6957f6fbafcfecf7b1f87/src/main/java/com/lmax/disruptor/RingBuffer.java#L34-L70","documentation":"Defensive check in RingBufferFields' constructor: the size reported by the sequencer is not a power of 2. Disruptor indexes slots with sequence & (bufferSize - 1), which requires exactly one bit set in the size. Like error 8, this normally cannot fire with standard sequencers because AbstractSequencer already rejects non-power-of-2 sizes; it guards against faulty custom Sequencer implementations or subclasses overriding getBufferSize().","triggerScenarios":"Passing a custom Sequencer whose getBufferSize() returns e.g. 1000 into a RingBuffer constructor; a test double returning an arbitrary number; subclassing that lazily changes bufferSize after construction.","commonSituations":"Custom sequencer for metrics/fault injection that bypasses AbstractSequencer; Mockito Sequencer mock with an unstubbed or arbitrary getBufferSize() return value.","solutions":["Return a power-of-2 capacity from custom Sequencer.getBufferSize().","Extend AbstractSequencer so constructor validation runs for you.","When mocking, stub getBufferSize() explicitly with a power of 2 such as 1024."],"exampleFix":"// before\nSequencer mock = mock(Sequencer.class);\nwhen(mock.getBufferSize()).thenReturn(1000);\nRingBuffer<Event> rb = new RingBuffer<>(Event::new, mock, new BlockingWaitStrategy());\n\n// after\nwhen(mock.getBufferSize()).thenReturn(1024);","handlingStrategy":"validation","validationCode":"int size = customSequencer.getBufferSize();\nif (Integer.bitCount(size) != 1) throw new IllegalArgumentException(\"sequencer bufferSize must be a power of 2, got \" + size);","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Delegate size handling to AbstractSequencer in custom sequencers.","Use power-of-2 constants in test fixtures."],"tags":["disruptor","ring-buffer","power-of-two","custom-sequencer","defensive-check"],"backgroundTag":null,"analyzedSha":"c871ca49826a6be7ada6957f6fbafcfecf7b1f87","analyzedAt":"2026-08-14T14:22:36.358Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}