alibaba/canal · error · IOException
Unexpected response {} while fetching binlog: packet #{}, le
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.
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)
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 #{}, le
- Received error packet: errno = {}, sqlstate = {} errmsg = {}
- illegal json data
- Unexpected packet with field_count= + body[0]
- command : ' + showSql + ' has an error!
AI-assisted analysis of alibaba/canal@87be50e876 (2026-08-14).
Data as JSON: /api/errors/4e73f52b1e636bbd.
Report an issue: GitHub.