{"record":{"id":"602b0c1578cbb577","repo":"XTLS/Xray-core","slug":"read-minecraft-custom-payload-channel-w","errorCode":null,"errorMessage":"read minecraft custom payload channel: %w","messagePattern":"read minecraft custom payload channel: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"transport/internet/finalmask/xmc/packet_stream.go","lineNumber":149,"sourceCode":"func (s *packetStream) localCustomPayloadID() int {\n\tif s.isClient {\n\t\treturn configurationServerboundCustomPayload\n\t}\n\treturn configurationClientboundCustomPayload\n}\n\nfunc (s *packetStream) remoteCustomPayloadID() int {\n\tif s.isClient {\n\t\treturn configurationClientboundCustomPayload\n\t}\n\treturn configurationServerboundCustomPayload\n}\n\nfunc parseCustomPayload(packet *mcPacket) ([]byte, bool, error) {\n\tr := bytes.NewReader(packet.data)\n\tvar channel String\n\tif err := channel.readFrom(r); err != nil {\n\t\treturn nil, false, fmt.Errorf(\"read minecraft custom payload channel: %w\", err)\n\t}\n\tif string(channel) != packetChannel {\n\t\treturn nil, false, nil\n\t}\n\tpayload := make([]byte, r.Len())\n\tif _, err := io.ReadFull(r, payload); err != nil {\n\t\treturn nil, false, fmt.Errorf(\"read minecraft custom payload data: %w\", err)\n\t}\n\treturn payload, true, nil\n}\n\nfunc (s *packetStream) writeKeepAlive(id Long) error {\n\ts.writeMu.Lock()\n\tdefer s.writeMu.Unlock()\n\tif err := writePacket(s.writer, configurationKeepAlive, &id); err != nil {\n\t\treturn fmt.Errorf(\"write minecraft keep-alive: %w\", err)\n\t}\n\treturn nil","sourceCodeStart":131,"sourceCodeEnd":167,"githubUrl":"https://github.com/XTLS/Xray-core/blob/7d214f8b094f75322fa3990f8aadad1c912f24f5/transport/internet/finalmask/xmc/packet_stream.go#L131-L167","documentation":"parseCustomPayload failed to read the channel-identifier String (Varint length + UTF-8 bytes) from a received custom-payload packet's data section. The packet body is already in memory, so this means the body is too short or the length prefix is malformed — internal framing corruption between the peers.","triggerScenarios":"Remote sends a 0x01/0x02 custom-payload packet whose data does not start with a valid Minecraft String; typically caused by packet-ID mismatch between client and server builds or stream corruption.","commonSituations":"Client and server run different xmc versions with changed packet layouts; a middlebox mangles the stream; interoperating with a plugin that reuses the same packet IDs with a different body format.","solutions":["Upgrade both endpoints to matching library versions","Capture traffic and confirm payload packets begin with the Varint length of \"xmc:data\"","Eliminate stream-altering middleboxes (compression proxies, TLS-terminating LBs) on the path","Treat the connection as unrecoverable and reconnect"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"n, err := stream.Read(buf)\nif err != nil && strings.Contains(err.Error(), \"custom payload channel\") {\n    log.Printf(\"peer speaks a different xmc variant: %v\", err)\n    conn.Close()\n}","preventionTips":["Pin library versions across endpoints","Avoid paths that rewrite stream bytes (compressing proxies, MITM TLS)","Log the channel error separately from I/O errors to identify protocol drift"],"tags":["go","minecraft","protocol","decode","custom-payload"],"backgroundTag":null,"analyzedSha":"7d214f8b094f75322fa3990f8aadad1c912f24f5","analyzedAt":"2026-08-15T14:26:24.325Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}