{"record":{"id":"33d464e24fe55bc1","repo":"LMAX-Exchange/disruptor","slug":"buffersize-must-be-a-power-of-2","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/AbstractSequencer.java","lineNumber":52,"sourceCode":"    protected final WaitStrategy waitStrategy;\n    protected final Sequence cursor = new Sequence(Sequencer.INITIAL_CURSOR_VALUE);\n    protected volatile Sequence[] gatingSequences = new Sequence[0];\n\n    /**\n     * Create with the specified buffer size and wait strategy.\n     *\n     * @param bufferSize   The total number of entries, must be a positive power of 2.\n     * @param waitStrategy The wait strategy used by this sequencer\n     */\n    public AbstractSequencer(final int bufferSize, final WaitStrategy waitStrategy)\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.bufferSize = bufferSize;\n        this.waitStrategy = waitStrategy;\n    }\n\n    /**\n     * @see Sequencer#getCursor()\n     */\n    @Override\n    public final long getCursor()\n    {\n        return cursor.get();\n    }\n\n    /**\n     * @see Sequencer#getBufferSize()\n     */","sourceCodeStart":34,"sourceCodeEnd":70,"githubUrl":"https://github.com/LMAX-Exchange/disruptor/blob/c871ca49826a6be7ada6957f6fbafcfecf7b1f87/src/main/java/com/lmax/disruptor/AbstractSequencer.java#L34-L70","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Change the buffer size to the nearest power of 2 (e.g. 1000 -> 1024, 3000 -> 4096).","If the size is dynamic, round up: int size = Integer.highestOneBit(desired - 1) << 1;","Add a startup assertion/util check so misconfiguration is caught with a clearer message."],"exampleFix":"// before\nRingBuffer<Event> rb = RingBuffer.createMultiProducer(Event::new, 1000);\n\n// after\nRingBuffer<Event> rb = RingBuffer.createMultiProducer(Event::new, 1024);","handlingStrategy":"validation","validationCode":"static int ceilPow2(int desired) {\n    return Integer.highestOneBit(Math.max(1, desired - 1)) << 1;\n}\n// use: ceilPow2(1000) == 1024","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Default to well-known powers of 2 (1024, 4096, 16384) in config templates.","When sizes are dynamic, always round up to the next power of 2 at the boundary."],"tags":["disruptor","configuration","ring-buffer","power-of-two","validation"],"backgroundTag":null,"analyzedSha":"c871ca49826a6be7ada6957f6fbafcfecf7b1f87","analyzedAt":"2026-08-14T14:22:36.358Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}