alibaba/canal · error · IllegalArgumentException

bufferSize must be a power of 2

Error message

bufferSize must be a power of 2

What it means

Thrown in MemoryEventStoreWithBuffer.start() when Integer.bitCount(bufferSize) != 1, i.e. bufferSize is not exactly a power of two. The ring buffer relies on bitwise masking (indexMask = bufferSize - 1; index = sequence & indexMask), which only wraps correctly for power-of-two sizes, so a non-compliant size is rejected at startup before the buffer can corrupt indices.

Source

Thrown at store/src/main/java/com/alibaba/otter/canal/store/memory/MemoryEventStoreWithBuffer.java:86

    private Condition         notFull       = lock.newCondition();
    private Condition         notEmpty      = lock.newCondition();

    private BatchMode         batchMode     = BatchMode.ITEMSIZE;                        // 默认为内存大小模式
    private boolean           ddlIsolation  = false;
    private boolean           raw           = true;                                      // 针对entry是否开启raw模式

    public MemoryEventStoreWithBuffer(){

    }

    public MemoryEventStoreWithBuffer(BatchMode batchMode){
        this.batchMode = batchMode;
    }

    public void start() throws CanalStoreException {
        super.start();
        if (Integer.bitCount(bufferSize) != 1) {
            throw new IllegalArgumentException("bufferSize must be a power of 2");
        }

        indexMask = bufferSize - 1;
        entries = new Event[bufferSize];
    }

    public void stop() throws CanalStoreException {
        super.stop();

        cleanAll();
    }

    public void put(List<Event> data) throws InterruptedException, CanalStoreException {
        if (data == null || data.isEmpty()) {
            return;
        }

        final ReentrantLock lock = this.lock;

View on GitHub (pinned to 87be50e876)

Solutions

  1. Set canal.instance.memory.buffer.size to the nearest power of two (e.g. 1024, 2048, 4096, 8192, 16384).
  2. Validate the configured value at deploy time with Integer.bitCount(size) == 1.
  3. Round up to the next power of two to preserve the intended capacity.

Example fix

// before
canal.instance.memory.buffer.size = 1000
// after
canal.instance.memory.buffer.size = 1024
Defensive patterns

Strategy: validation

Validate before calling

int size = config.getBufferSize();
if (Integer.bitCount(size) != 1 || size <= 0) {
    throw new IllegalArgumentException(
        "bufferSize must be a power of 2, got " + size + "; nearest valid: " + Integer.highestOneBit(size - 1) * 2);
}

Prevention

When it happens

Trigger: Configuring canal.instance.memory.buffer.size to a value that is not a power of two (e.g. 1000, 3000, 50000) and starting the instance. The start() guard computes bit count and aborts.

Common situations: Operator sets a 'round' buffer size like 1000 or 16380 expecting decimal sizing; copy-pasting a size from another system; misreading the property as byte count vs entry count.

Related errors


AI-assisted analysis of alibaba/canal@87be50e876 (2026-08-14). Data as JSON: /api/errors/0a485216013d01e0. Report an issue: GitHub.