alibaba/canal · error · ServerIdNotMatchException
unexpected serverId + serverId + in binlog file !
Error message
unexpected serverId + serverId + in binlog file !
What it means
Thrown as ServerIdNotMatchException by LocalBinLogConnection.checkServerId in the NON-RDS-OSS branch when a binlog event's serverId differs from the configured serverId (serverId != 0). This guards local binlog replay so only events from the intended MySQL server_id are processed, filtering out any foreign events.
Source
Thrown at parse/src/main/java/com/alibaba/otter/canal/parse/inbound/mysql/LocalBinLogConnection.java:173
* 2. rdsOos 高可用模式下解析 binlog
* 会有两个 serverId,分别对应着主从节点 binlog解析出来的 serverId 主从的关系可能会变, 但是 serverId一直都会是这两个
* serverId
*
* @param event
*/
private void checkServerId(LogEvent event) {
if (serverId != 0 && event.getServerId() != serverId) {
if (isRdsOssMode()) {
// 第一次添加主从信息
if (firstUpdateRdsOssMasterSlave) {
firstUpdateRdsOssMasterSlave = false;
rdsOssMasterSlaveInfo.add(event.getServerId());
} else if (!rdsOssMasterSlaveInfo.contains(event.getServerId())) {
// 主从节点信息之外的节点信息
throw new ServerIdNotMatchException("unexpected rds serverId " + serverId + " in binlog file !");
}
} else {
throw new ServerIdNotMatchException("unexpected serverId " + serverId + " in binlog file !");
}
}
}
public void dump(long timestampMills, SinkFunction func) throws IOException {
List<File> currentBinlogs = binlogs.currentBinlogs();
File current = currentBinlogs.get(currentBinlogs.size() - 1);
long timestampSeconds = timestampMills / 1000;
String binlogFilename = null;
long binlogFileOffset = 0;
FileLogFetcher fetcher = new FileLogFetcher(bufferSize);
LogDecoder decoder = new LogDecoder();
decoder.handle(LogEvent.FORMAT_DESCRIPTION_EVENT);
decoder.handle(LogEvent.QUERY_EVENT);
decoder.handle(LogEvent.XID_EVENT);
LogContext context = new LogContext();
View on GitHub (pinned to 87be50e876)
Solutions
- Set LocalBinLogConnection.serverId to the actual server_id of the binlog files being replayed (or 0 to disable the check).
- Ensure the binlog directory only contains files from the intended instance.
- After a master failover, update serverId to the new master's server_id or disable the check (serverId=0) if mixing is acceptable.
- Verify you are not accidentally pointing at a standby's binlogs when serverId is set for the primary.
Example fix
// before localBinLogConnection.setServerId(1); // wrong id // after localBinLogConnection.setServerId(3306actualServerId); // or disable the filter localBinLogConnection.setServerId(0);
Defensive patterns
Strategy: validation
Validate before calling
long actualServerId = readFirstEventServerId(new File(directory, firstBinlog));
if (conn.getServerId() != 0 && conn.getServerId() != actualServerId) {
throw new IllegalStateException("configured serverId=" + conn.getServerId() + " != binlog serverId=" + actualServerId);
} Try / catch
try { conn.dump(...); }
catch (ServerIdNotMatchException e) {
conn.setServerId(0); // disable filter if mixing is acceptable
conn.dump(...);
} Prevention
- Set serverId to the binlog's actual server_id, or 0 to disable.
- Keep one instance's binlogs per replay directory.
- Update serverId after a master failover.
When it happens
Trigger: checkServerId(event): serverId != 0, event.getServerId() != serverId, and isRdsOssMode() is false, so the else-branch throws. Triggered during local binlog dump/fetch when an event carries a server_id different from the configured one.
Common situations: LocalBinLogConnection.serverId is misconfigured (does not match the binlog's server_id), the binlog directory contains files from a different MySQL instance, or a HA failover changed the master server_id and the replay is now seeing the new id while serverId is pinned to the old one.
Related errors
- unexpected rds serverId + serverId + in binlog file !
- binlog: + binlogfilename + is not found
- can't find start position for {}
- parse failed
- Invalid charset id: {}
AI-assisted analysis of alibaba/canal@87be50e876 (2026-08-14).
Data as JSON: /api/errors/58e64438523cb88d.
Report an issue: GitHub.