alibaba/canal · error · IOException
Unexpected response while fetching binlog: packet # , len =
Error message
Unexpected response {} while fetching binlog: packet #{}, len = {} What it means
Thrown in the binlog packet reader when the response mark byte is neither 0 (OK / start of event data), 255 (ERR), nor 254 (EOF). The code comments it as 'Should not happen', meaning the stream no longer matches the MySQL replication protocol framing.
Solutions
- Capture the reported mark value and packet number - a consistent non-protocol value suggests a wrong endpoint; an isolated one suggests corruption.
- Verify the host:port is the real mysqld (or a faithful replication proxy), not a load-balanced non-mysql listener.
- Re-establish the connection from a clean binlog position to recover from a one-off corrupted packet.
- If behind a proxy, bypass it temporarily to confirm it is not altering the byte stream.
- Check for packet-size limits: a payload split across MAX_PACKET_LENGTH multi-packets may have been reassembled incorrectly.
Defensive patterns
Strategy: retry
Validate before calling
// Confirm the endpoint speaks the mysql replication protocol
try (Socket so = new Socket(host, port)) {
byte[] hdr = new byte[4];
int n = so.getInputStream().read(hdr);
if (n < 4 || hdr[3] != 0) throw new IOException("endpoint is not a mysql server");
} Try / catch
try { while (fetcher.fetch()) { /* decode */ } }
catch (IOException e) {
if (e.getMessage().startsWith("Unexpected response")) {
logger.error("protocol corruption mid-stream - reconnecting", e);
reconnectFromLastPosition();
} else throw e;
} Prevention
- Point only at a real mysqld (or a faithful replication proxy), not a generic LB.
- Reconnect from the last recorded position on a protocol error.
- Bypass intermediaries when diagnosing to isolate corruption sources.
When it happens
Trigger: A fetched packet's leading payload byte is an unexpected value (not 0/255/254). This follows a successful packet-length read, so the framing is intact but the payload marker is invalid - i.e. mid-stream corruption, a non-mysql service, or bytes from a different protocol interleaved into the socket.
Common situations: Network-level corruption / TLS mis-termination injecting garbage; connecting to a port that serves a different MySQL-like protocol; a proxy (MaxScale, ProxySQL) mangling the replication stream; partial packet after a master crash; version skew producing a protocol extension the reader doesn't understand.
Related errors
- Unexpected response while fetching binlog: packet # , len =
- command : 'show binlog events limit 1' has an error!
- command : ' + showSql + ' has an error!
- illegal json data
- Received error packet: errno =
AI-assisted analysis of alibaba/canal@87be50e876 (2026-08-14).
Data as JSON: /api/errors/4e73f52b1e636bbd.
Report an issue: GitHub.
Appendix: source
Thrown at dbsync/src/main/java/com/taobao/tddl/dbsync/binlog/DirectLogFetcher.java:316
if (mark == 255) // error from master
{
// Indicates an error, for example trying to fetch from
// wrong
// binlog position.
position = NET_HEADER_SIZE + 1;
final int errno = getInt16();
String sqlstate = forward(1).getFixString(SQLSTATE_LENGTH);
String errmsg = getFixString(limit - position);
throw new IOException("Received error packet:" + " errno = " + errno + ", sqlstate = " + sqlstate
+ " errmsg = " + errmsg);
} else if (mark == 254) {
// Indicates end of stream. It's not clear when this would
// be sent.
logger.warn("Received EOF packet from server, apparent" + " master disconnected.");
return false;
} else {
// Should not happen.
throw new IOException("Unexpected response " + mark + " while fetching binlog: packet #" + netnum
+ ", len = " + netlen);
}
}
// The first packet is a multi-packet, concatenate the packets.
while (netlen == MAX_PACKET_LENGTH) {
if (!fetch0(0, NET_HEADER_SIZE)) {
logger.warn("Reached end of input stream while fetching header");
return false;
}
netlen = getUint24(PACKET_LEN_OFFSET);
netnum = getUint8(PACKET_SEQ_OFFSET);
if (!fetch0(limit, netlen)) {
logger.warn("Reached end of input stream: packet #" + netnum + ", len = " + netlen);
return false;
}
}
View on GitHub (pinned to 87be50e876)