alibaba/canal · error · CanalClientException

expect handshake but found other type.

Error message

expect handshake but found other type.

What it means

Thrown in doConnect() when the first packet's version is 1 but its type is not PacketType.HANDSHAKE. The admin connector expects the server to open with a handshake containing the auth seed; any other type means the connection state is wrong.

Source

Thrown at admin/admin-web/src/main/java/com/alibaba/otter/canal/admin/connector/SimpleAdminConnector.java:77

    @Override
    public void connect() throws ServiceException {
        try {
            if (connected) {
                return;
            }

            channel = SocketChannel.open();
            channel.socket().setSoTimeout(soTimeout);
            channel.connect(address);
            readableChannel = Channels.newChannel(channel.socket().getInputStream());
            writableChannel = Channels.newChannel(channel.socket().getOutputStream());
            Packet p = Packet.parseFrom(readNextPacket());
            if (p.getVersion() != 1) {
                throw new CanalClientException("unsupported version at this client.");
            }

            if (p.getType() != PacketType.HANDSHAKE) {
                throw new CanalClientException("expect handshake but found other type.");
            }

            Handshake handshake = Handshake.parseFrom(p.getBody());
            ByteString seed = handshake.getSeeds(); // seed for auth
            String newPasswd = passwd;
            if (passwd != null) {
                // encode passwd
                newPasswd = SecurityUtil.byte2HexStr(SecurityUtil.scramble411(passwd.getBytes(), seed.toByteArray()));
            }

            ClientAuth ca = ClientAuth.newBuilder()
                .setUsername(user != null ? user : "")
                .setPassword(ByteString.copyFromUtf8(newPasswd != null ? newPasswd : ""))
                .setNetReadTimeout(idleTimeout)
                .setNetWriteTimeout(idleTimeout)
                .build();
            writeWithHeader(Packet.newBuilder()
                .setType(PacketType.CLIENTAUTHENTICATION)

View on GitHub (pinned to 87be50e876)

Solutions

  1. Verify the target is the admin port and not the streaming/data port.
  2. Ensure a fresh SocketChannel is used (the code only connects if !connected; force a reconnect).
  3. Align canal-admin and canal-server versions so the expected handshake packet is sent.
  4. Check no proxy/LB is injecting bytes before the canal handshake.
Defensive patterns

Strategy: try-catch

Try / catch

try {
    connector.connect();
} catch (CanalClientException e) {
    if (e.getMessage().contains("expect handshake")) {
        // likely wrong port or dirty channel; reconnect on a fresh channel
    }
    throw e;
}

Prevention

When it happens

Trigger: The parsed Packet has type != HANDSHAKE on the first read. Occurs when connecting to a service that sends a different packet first, when the channel is mid-session from a previous connection, or when bytes are misaligned.

Common situations: Connecting to the wrong port (data/streaming port sends different packets); reconnecting to a channel not fully reset; partial bytes from a prior failed handshake left in the stream; protocol version skew.

Understand the failure class

Related errors


AI-assisted analysis of alibaba/canal@87be50e876 (2026-08-14). Data as JSON: /api/errors/19196ca8c8d96546. Report an issue: GitHub.