{"record":{"id":"4e73f52b1e636bbd","repo":"alibaba/canal","slug":"unexpected-response-while-fetching-binlog-pack","errorCode":null,"errorMessage":"Unexpected response {} while fetching binlog: packet #{}, len = {}","messagePattern":"Unexpected response (.+?) while fetching binlog: packet #(.+?), len = (.+?)","errorType":"exception","errorClass":"IOException","httpStatus":null,"severity":"error","filePath":"dbsync/src/main/java/com/taobao/tddl/dbsync/binlog/DirectLogFetcher.java","lineNumber":316,"sourceCode":"                if (mark == 255) // error from master\r\n                {\r\n                    // Indicates an error, for example trying to fetch from\r\n                    // wrong\r\n                    // binlog position.\r\n                    position = NET_HEADER_SIZE + 1;\r\n                    final int errno = getInt16();\r\n                    String sqlstate = forward(1).getFixString(SQLSTATE_LENGTH);\r\n                    String errmsg = getFixString(limit - position);\r\n                    throw new IOException(\"Received error packet:\" + \" errno = \" + errno + \", sqlstate = \" + sqlstate\r\n                                          + \" errmsg = \" + errmsg);\r\n                } else if (mark == 254) {\r\n                    // Indicates end of stream. It's not clear when this would\r\n                    // be sent.\r\n                    logger.warn(\"Received EOF packet from server, apparent\" + \" master disconnected.\");\r\n                    return false;\r\n                } else {\r\n                    // Should not happen.\r\n                    throw new IOException(\"Unexpected response \" + mark + \" while fetching binlog: packet #\" + netnum\r\n                                          + \", len = \" + netlen);\r\n                }\r\n            }\r\n\r\n            // The first packet is a multi-packet, concatenate the packets.\r\n            while (netlen == MAX_PACKET_LENGTH) {\r\n                if (!fetch0(0, NET_HEADER_SIZE)) {\r\n                    logger.warn(\"Reached end of input stream while fetching header\");\r\n                    return false;\r\n                }\r\n\r\n                netlen = getUint24(PACKET_LEN_OFFSET);\r\n                netnum = getUint8(PACKET_SEQ_OFFSET);\r\n                if (!fetch0(limit, netlen)) {\r\n                    logger.warn(\"Reached end of input stream: packet #\" + netnum + \", len = \" + netlen);\r\n                    return false;\r\n                }\r\n            }\r","sourceCodeStart":298,"sourceCodeEnd":334,"githubUrl":"https://github.com/alibaba/canal/blob/87be50e87686a3e8af08c368d0e1ffd1f59eb04a/dbsync/src/main/java/com/taobao/tddl/dbsync/binlog/DirectLogFetcher.java#L298-L334","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":null,"handlingStrategy":"retry","validationCode":"// Confirm the endpoint speaks the mysql replication protocol\ntry (Socket so = new Socket(host, port)) {\n    byte[] hdr = new byte[4];\n    int n = so.getInputStream().read(hdr);\n    if (n < 4 || hdr[3] != 0) throw new IOException(\"endpoint is not a mysql server\");\n}","typeGuard":null,"tryCatchPattern":"try { while (fetcher.fetch()) { /* decode */ } }\ncatch (IOException e) {\n    if (e.getMessage().startsWith(\"Unexpected response\")) {\n        logger.error(\"protocol corruption mid-stream - reconnecting\", e);\n        reconnectFromLastPosition();\n    } else throw e;\n}","preventionTips":["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."],"tags":["binlog","protocol","network","corruption","mysql"],"backgroundTag":null,"analyzedSha":"87be50e87686a3e8af08c368d0e1ffd1f59eb04a","analyzedAt":"2026-08-14T04:30:11.918Z","schemaVersion":2},"datasetVersion":"2026-08-14T05:17:29.042Z"}