{"record":{"id":"729cd6bc0086a096","repo":"LMAX-Exchange/disruptor","slug":"buffersize-must-be-a-power-of-2-729cd6","errorCode":null,"errorMessage":"bufferSize must be a power of 2","messagePattern":"bufferSize must be a power of 2","errorType":"exception","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"src/main/java/com/lmax/disruptor/RingBuffer.java","lineNumber":56,"sourceCode":"    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    }\n\n    protected final E elementAt(final long sequence)\n    {\n        return entries[BUFFER_PAD + (int) (sequence & indexMask)];","sourceCodeStart":38,"sourceCodeEnd":74,"githubUrl":"https://github.com/LMAX-Exchange/disruptor/blob/c871ca49826a6be7ada6957f6fbafcfecf7b1f87/src/main/java/com/lmax/disruptor/RingBuffer.java#L38-L74","documentation":"Defensive check in RingBufferFields: the capacity from the sequencer is less than 1. Redundant with AbstractSequencer's own check for standard sequencers; it protects RingBuffer against custom Sequencer implementations returning 0 or negative sizes, which would make the backing entry array unusable.","triggerScenarios":"Constructing a RingBuffer over a custom or mocked Sequencer whose getBufferSize() returns 0/negative; delegating constructors in RingBuffer subclasses that pass an uninitialised size.","commonSituations":"Mockito default return of 0 for unstubbed getBufferSize(); custom sequencer wrapper that drops the bufferSize field.","solutions":["Ensure the supplied Sequencer reports a positive power-of-2 capacity.","Extend AbstractSequencer instead of implementing Sequencer directly.","Stub getBufferSize() in tests with a valid size."],"exampleFix":"// before\nwhen(mockSequencer.getBufferSize()).thenReturn(0); // or left unstubbed\n\n// after\nwhen(mockSequencer.getBufferSize()).thenReturn(1024);","handlingStrategy":"validation","validationCode":"if (sequencer.getBufferSize() < 1) throw new IllegalArgumentException(\"invalid sequencer bufferSize\");","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Never ship a Sequencer implementation without a positive power-of-2 getBufferSize().","Add a contract test for custom sequencers covering size invariants."],"tags":["disruptor","ring-buffer","custom-sequencer","defensive-check","validation"],"backgroundTag":null,"analyzedSha":"c871ca49826a6be7ada6957f6fbafcfecf7b1f87","analyzedAt":"2026-08-14T14:22:36.358Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}