alibaba/canal · error · IllegalArgumentException
bufferSize must be a power of 2
Error message
bufferSize must be a power of 2
What it means
Thrown as IllegalArgumentException by EventTransactionBuffer.start because the ring buffer implementation uses an index mask (bufferSize - 1) for O(1) slot addressing, which only works when bufferSize is a power of two. Integer.bitCount(bufferSize) != 1 is the power-of-two check; any other size breaks the masking logic.
Source
Thrown at parse/src/main/java/com/alibaba/otter/canal/parse/inbound/EventTransactionBuffer.java:43
private CanalEntry.Entry[] entries;
private AtomicLong putSequence = new AtomicLong(INIT_SQEUENCE); // 代表当前put操作最后一次写操作发生的位置
private AtomicLong flushSequence = new AtomicLong(INIT_SQEUENCE); // 代表满足flush条件后最后一次数据flush的时间
private TransactionFlushCallback flushCallback;
public EventTransactionBuffer(){
}
public EventTransactionBuffer(TransactionFlushCallback flushCallback){
this.flushCallback = flushCallback;
}
public void start() throws CanalStoreException {
super.start();
if (Integer.bitCount(bufferSize) != 1) {
throw new IllegalArgumentException("bufferSize must be a power of 2");
}
Assert.notNull(flushCallback, "flush callback is null!");
indexMask = bufferSize - 1;
entries = new CanalEntry.Entry[bufferSize];
}
public void stop() throws CanalStoreException {
putSequence.set(INIT_SQEUENCE);
flushSequence.set(INIT_SQEUENCE);
entries = null;
super.stop();
}
public void add(List<CanalEntry.Entry> entrys) throws InterruptedException {
for (CanalEntry.Entry entry : entrys) {
add(entry);View on GitHub (pinned to 87be50e876)
Solutions
- Set canal.instance.transaction.buffer.size to a power of two (e.g. 1024, 2048, 4096, 8192).
- If unsure, remove the override to use the default power-of-two value.
- When sizing, round up to the next power of two rather than a round decimal.
Example fix
# before canal.instance.transaction.buffer.size = 2000 # after canal.instance.transaction.buffer.size = 2048
Defensive patterns
Strategy: validation
Validate before calling
static int nextPow2(int n) { return n <= 0 ? 1 : Integer.highestOneBit((n - 1) << 1 | 1); }
int safe = (Integer.bitCount(bufferSize) == 1) ? bufferSize : nextPow2(bufferSize);
buffer.setBufferSize(safe); Type guard
boolean isPow2(int n) { return n > 0 && (n & (n - 1)) == 0; } Prevention
- Set canal.instance.transaction.buffer.size to a power of two.
- Round buffer sizes up to the next power of two when tuning.
- Validate config in a unit test that asserts power-of-two.
When it happens
Trigger: EventTransactionBuffer.start() runs when the parser starts the transaction buffer. If canal.instance.transaction.buffer.size (the bufferSize) is not 1, 2, 4, 8, ... the check fails. The mask indexMask = bufferSize - 1 and CanalEntry.Entry[bufferSize] array rely on the power-of-two invariant.
Common situations: A user sets canal.instance.transaction.buffer.size to a non-power-of-two value like 1000, 2048 is fine but 2000 is not, or leaves a custom value from tuning. Default is typically a power of two; overriding it incorrectly triggers this at startup.
Related errors
- canal.adminUser is empty , pls check https://github.com/alib
- canal.adminPasswd is empty , pls check https://github.com/al
- No clickhouse adapter found for config key: {}
- ERROR Config: {} {}
- ERROR load Config: {} {}
AI-assisted analysis of alibaba/canal@87be50e876 (2026-08-14).
Data as JSON: /api/errors/0496fb07eee3c72e.
Report an issue: GitHub.