alibaba/canal · error · IllegalArgumentException
Unexcepted limit: {}
Error message
Unexcepted limit: {} What it means
Thrown by FileLogFetcher.fetch() in the else branch when 'limit' takes an unexpected value that violates the method's internal buffer-state invariant (the code comments it 'Should not happen'). It is a defensive guard indicating the fetcher's buffer positions got into an inconsistent state, almost always a consequence of upstream corruption rather than normal operation.
Source
Thrown at dbsync/src/main/java/com/taobao/tddl/dbsync/binlog/FileLogFetcher.java:158
return true;
} else {
ensureCapacity((int) eventLen);
}
}
System.arraycopy(buffer, origin, buffer, 0, limit);
position -= origin;
origin = 0;
final int len = fin.read(buffer, limit, buffer.length - limit);
if (len >= 0) {
limit += len;
/* More binlog to fetch */
return true;
}
} else {
/* Should not happen. */
throw new IllegalArgumentException("Unexcepted limit: " + limit);
}
/* Reach binlog file end */
return false;
}
/**
* {@inheritDoc}
*
* @see com.taobao.tddl.dbsync.binlog.LogFetcher#close()
*/
public void close() throws IOException {
if (fin != null) {
fin.close();
}
fin = null;
}
View on GitHub (pinned to 87be50e876)
Solutions
- Treat this as data corruption: re-verify the binlog file with mysqlbinlog on the source; if it fails there too, the file is damaged.
- Ensure a single FileLogFetcher instance is not shared across threads (it is not thread-safe).
- Restart the fetch from an earlier known-good position/file rather than continuing past the corrupt region.
- If reproducible on a known-good file, check for a subclass overriding LogBuffer/LogFetcher methods that mismanage position/limit.
Defensive patterns
Strategy: try-catch
Validate before calling
// Guard the fetcher's buffer invariant defensively in a wrapper
public boolean safeFetch(FileLogFetcher f) throws IOException {
try { return f.fetch(); }
catch (IllegalArgumentException e) {
if (e.getMessage().startsWith("Unexcepted limit"))
throw new IOException("binlog corruption / unsafe concurrent use", e);
throw e;
}
} Try / catch
try { while (fetcher.fetch()) { /* decode */ } }
catch (IllegalArgumentException e) {
if (e.getMessage().startsWith("Unexcepted limit"))
throw new IOException("file/log fetcher state corrupted - re-open from good position", e);
throw e;
} Prevention
- Never share one FileLogFetcher across threads.
- Validate the binlog file with mysqlbinlog on the source before replaying.
- Restart from a known-good position on a state-invariant error.
When it happens
Trigger: fetch() computes buffer state and reaches the else branch whose precondition on 'limit' is not met - i.e. limit is negative or larger than buffer capacity after the compact/read logic, which should be impossible given the preceding arithmetic.
Common situations: A corrupted/truncated binlog file feeding the reader inconsistent event lengths; a race where the same FileLogFetcher is used concurrently (not thread-safe); memory corruption or a bug in a downstream subclass overriding ensureCapacity/forward that breaks position accounting.
Related errors
- Unexpected response {} while fetching binlog: packet #{}, le
- No binlog file header
- Error binlog file header: {}
- illegal json data
- Unexpected response {} while fetching binlog: packet #{}, le
AI-assisted analysis of alibaba/canal@87be50e876 (2026-08-14).
Data as JSON: /api/errors/403e4cb178c81eae.
Report an issue: GitHub.