{"record":{"id":"371ad433690786f5","repo":"alibaba/canal","slug":"unexpected-packet-type-p-gettype","errorCode":null,"errorMessage":"unexpected packet type: ${p.getType()}","messagePattern":"unexpected packet type: (.+?)","errorType":"exception","errorClass":"CanalClientException","httpStatus":null,"severity":"error","filePath":"connector/core/src/main/java/com/alibaba/otter/canal/connector/core/util/CanalMessageSerializerUtil.java","lineNumber":123,"sourceCode":"                        Message result = new Message(messages.getBatchId());\n                        if (lazyParseEntry) {\n                            // byteString\n                            result.setRawEntries(messages.getMessagesList());\n                            result.setRaw(true);\n                        } else {\n                            for (ByteString byteString : messages.getMessagesList()) {\n                                result.addEntry(CanalEntry.Entry.parseFrom(byteString));\n                            }\n                            result.setRaw(false);\n                        }\n                        return result;\n                    }\n                    case ACK: {\n                        CanalPacket.Ack ack = CanalPacket.Ack.parseFrom(p.getBody());\n                        throw new CanalClientException(\"something goes wrong with reason: \" + ack.getErrorMessage());\n                    }\n                    default: {\n                        throw new CanalClientException(\"unexpected packet type: \" + p.getType());\n                    }\n                }\n            }\n        } catch (Exception e) {\n            throw new CanalClientException(\"deserializer failed by \" + e.getMessage(), e);\n        }\n    }\n}\n","sourceCodeStart":105,"sourceCodeEnd":132,"githubUrl":"https://github.com/alibaba/canal/blob/87be50e87686a3e8af08c368d0e1ffd1f59eb04a/connector/core/src/main/java/com/alibaba/otter/canal/connector/core/util/CanalMessageSerializerUtil.java#L105-L132","documentation":"Thrown by CanalMessageSerializerUtil.deserializer when a parsed CanalPacket.Packet has a type other than MESSAGES or ACK. The canal wire protocol defines many packet types (HANDSHAKE, CLIENTAUTH, SUBSCRIPTION, GET, etc.), but this MQ-side deserializer only understands data-carrying MESSAGES packets, so any other type is treated as corrupt or misrouted input. The actual type value is interpolated into the message so you can see which unexpected type arrived.","triggerScenarios":"CanalMessageSerializerUtil.deserializer(data) is called on a byte[] that was not produced by CanalMessageSerializerUtil.serializer — for example bytes from a canal server handshake/auth response, a raw protobuf that is not a CanalPacket.Packet, or bytes read off the wrong MQ topic. Also reachable when a producer sends a custom packet type the consumer switch does not case on.","commonSituations":"Subscribing a canal MQ consumer to a topic that carries non-canal payloads; version skew where a newer canal server emits a packet type the older connector deserializer does not know; feeding the deserializer a raw Entry/RowChange byte array instead of a full Packet; reading a handshake-stage message that leaked into the data path.","solutions":["Confirm the bytes came from CanalMessageSerializerUtil.serializer (a CanalPacket.Packet with type MESSAGES) and that you are consuming the correct canal MQ topic.","Check canal server and connector versions match — an unknown packet type usually means the client deserializer is older than the producer.","If you hold a raw CanalEntry.Entry or RowChange, parse it directly with CanalEntry.Entry.parseFrom / CanalEntry.RowChange.parseFrom instead of routing it through CanalMessageSerializerUtil.deserializer.","Inspect p.getType() from the error text to identify which protocol stage produced the packet, then fix the upstream so only MESSAGES packets reach this deserializer."],"exampleFix":"// before\nMessage msg = CanalMessageSerializerUtil.deserializer(data);\n\n// after — guard against non-MESSAGES bytes before deserializing\nCanalPacket.Packet p = CanalPacket.Packet.parseFrom(data);\nif (p.getType() != CanalPacket.PacketType.MESSAGES) {\n    throw new IllegalArgumentException(\"expect MESSAGES packet, got \" + p.getType());\n}\nMessage msg = CanalMessageSerializerUtil.deserializer(data);","handlingStrategy":"validation","validationCode":"// Validate the payload is a MESSAGES packet before deserializing\nCanalPacket.Packet p = CanalPacket.Packet.parseFrom(data);\nif (p.getType() != CanalPacket.PacketType.MESSAGES) {\n    throw new IllegalArgumentException(\n        \"Cannot deserialize non-MESSAGES packet: \" + p.getType());\n}\nMessage msg = CanalMessageSerializerUtil.deserializer(data);","typeGuard":"static boolean isCanalMessagesPacket(byte[] data) {\n    try {\n        return CanalPacket.Packet.parseFrom(data).getType()\n            == CanalPacket.PacketType.MESSAGES;\n    } catch (com.google.protobuf.InvalidProtocolBufferException e) {\n        return false;\n    }\n}","tryCatchPattern":"try {\n    Message msg = CanalMessageSerializerUtil.deserializer(data);\n} catch (CanalClientException e) {\n    if (e.getMessage() != null && e.getMessage().startsWith(\"unexpected packet type\")) {\n        // wrong source / version mismatch — do not retry, fix upstream\n        log.error(\"Non-MESSAGES packet received; check topic and canal versions\", e);\n    }\n    throw e;\n}","preventionTips":["Only feed CanalMessageSerializerUtil.serializer output into the matching deserializer.","Keep canal server and connector versions aligned to avoid unknown packet types.","Consume dedicated canal MQ topics that carry only MESSAGES packets."],"tags":["protobuf","protocol","serialization","canal-connector","data-corruption"],"backgroundTag":null,"analyzedSha":"87be50e87686a3e8af08c368d0e1ffd1f59eb04a","analyzedAt":"2026-08-14T04:30:11.918Z","schemaVersion":2},"datasetVersion":"2026-08-14T05:17:29.042Z"}