{"record":{"id":"06c513c002dcc1a0","repo":"alibaba/canal","slug":"unexpected-response-while-fetching-binlog-pack-06c513","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":"parse/src/main/java/com/alibaba/otter/canal/parse/inbound/mysql/dbsync/DirectLogFetcher.java","lineNumber":121,"sourceCode":"                    String errmsg = getFixString(limit - position);\n                    if (StringUtils.containsIgnoreCase(errmsg, \"not find first log file name\")\n                        || StringUtils.containsIgnoreCase(errmsg, \"purged binary logs\")) {\n                        // 开始 dump 后，server 位点过期，DUMP 和 DUMP_GTID 两种错误信息\n                        throw new ServerLogPurgedException(\n                            \" errno = \" + errno + \", sqlstate = \" + sqlstate + \" errmsg = \" + errmsg);\n                    }\n\n                    throw new IOException(\"Received error packet:\" + \" errno = \" + errno + \", sqlstate = \" + sqlstate\n                                          + \" errmsg = \" + errmsg);\n                } else if (mark == 254) {\n                    // Indicates end of stream. It's not clear when this would\n                    // be sent.\n                    logger.warn(\"Received EOF packet from server, apparent\"\n                                + \" master disconnected. It's may be duplicate slaveId , check instance config\");\n                    return false;\n                } else {\n                    // Should not happen.\n                    throw new IOException(\"Unexpected response \" + mark + \" while fetching binlog: packet #\" + netnum\n                                          + \", len = \" + netlen);\n                }\n            }\n\n            // if mysql is in semi mode\n            if (issemi) {\n                // parse semi mark\n                int semimark = getUint8(NET_HEADER_SIZE + 1);\n                int semival = getUint8(NET_HEADER_SIZE + 2);\n                this.semival = semival;\n            }\n\n            // The first packet is a multi-packet, concatenate the packets.\n            while (netlen == MAX_PACKET_LENGTH) {\n                if (!fetch0(0, NET_HEADER_SIZE)) {\n                    logger.warn(\"Reached end of input stream while fetching header\");\n                    return false;\n                }","sourceCodeStart":103,"sourceCodeEnd":139,"githubUrl":"https://github.com/alibaba/canal/blob/87be50e87686a3e8af08c368d0e1ffd1f59eb04a/parse/src/main/java/com/alibaba/otter/canal/parse/inbound/mysql/dbsync/DirectLogFetcher.java#L103-L139","documentation":"Thrown as IOException('Unexpected response') when the first byte (mark) of a binlog dump response packet is not 0 (OK), 255 (error), or 254 (EOF). Canal considers this a protocol violation — the MySQL replication protocol defines only those three markers for the initial byte of a dump response. The exception includes the unexpected mark value, the packet sequence number, and the length.","triggerScenarios":"DirectLogFetcher.fetch() reads a packet whose first byte after the net header is an unrecognized value. This should never happen with a standards-compliant MySQL server. It indicates data corruption, a man-in-the-middle proxy mangling the protocol, or an incompatible/undocumented server behavior.","commonSituations":"A TCP proxy or connection pooler (e.g. ProxySQL, HAProxy in TCP mode) is interfering with the raw replication protocol. A network glitch corrupted the byte stream. The server is not actually MySQL (e.g. a compatible database with divergent protocol). SSL/TLS handshake left residual bytes in the buffer.","solutions":["Ensure Canal connects directly to the MySQL server (no TCP proxy in between that doesn't understand the replication protocol).","Check for network corruption: verify MTU settings, switch/NIC errors on the host.","If using SSL, verify the SSL configuration is correct on both sides (canal SSL settings + MySQL SSL settings).","Check the MySQL server version — Canal should be compatible with the server's binlog protocol version."],"exampleFix":"# before — routing through a generic TCP proxy\ncanal.instance.master.address=proxysql.internal:3306\n\n# after — connect directly to the MySQL primary\ncanal.instance.master.address=mysql-primary.internal:3306","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try {\n    directLogFetcher.fetch();\n} catch (IOException e) {\n    if (e.getMessage().startsWith(\"Unexpected response\")) {\n        // Protocol violation — likely a proxy or network corruption\n        logger.error(\"Protocol violation in binlog stream, check for proxies/corruption\", e);\n        // Re-establish the connection from scratch\n        reconnectToMySQL();\n    } else {\n        throw e;\n    }\n}","preventionTips":["Connect Canal directly to the MySQL primary — avoid TCP proxies that don't understand the replication protocol.","Verify SSL/TLS configuration matches on both Canal and MySQL sides.","Monitor network error rates on the Canal host."],"tags":["mysql","protocol","binlog","corruption","network"],"backgroundTag":null,"analyzedSha":"87be50e87686a3e8af08c368d0e1ffd1f59eb04a","analyzedAt":"2026-08-14T04:30:11.918Z","schemaVersion":2},"datasetVersion":"2026-08-14T05:17:29.042Z"}