{"record":{"id":"03287c7999eb4e47","repo":"XTLS/Xray-core","slug":"read-minecraft-packet-stream-w","errorCode":null,"errorMessage":"read minecraft packet stream: %w","messagePattern":"read minecraft packet stream: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"transport/internet/finalmask/xmc/packet_stream.go","lineNumber":69,"sourceCode":"\nfunc (s *packetStream) Read(p []byte) (int, error) {\n\tif len(p) == 0 {\n\t\treturn 0, nil\n\t}\n\n\ts.readMu.Lock()\n\tdefer s.readMu.Unlock()\n\n\tif len(s.pending) > 0 {\n\t\tn := copy(p, s.pending)\n\t\ts.pending = s.pending[n:]\n\t\treturn n, nil\n\t}\n\n\tfor {\n\t\tpacket, err := readPacket(s.reader)\n\t\tif err != nil {\n\t\t\treturn 0, fmt.Errorf(\"read minecraft packet stream: %w\", err)\n\t\t}\n\n\t\tif packet.packetID == s.remoteCustomPayloadID() {\n\t\t\tpayload, ok, err := parseCustomPayload(packet)\n\t\t\tif err != nil {\n\t\t\t\treturn 0, err\n\t\t\t}\n\t\t\tif !ok || len(payload) == 0 {\n\t\t\t\tcontinue\n\t\t\t}\n\n\t\t\tn := copy(p, payload)\n\t\t\tif n < len(payload) {\n\t\t\t\ts.pending = append(s.pending[:0], payload[n:]...)\n\t\t\t}\n\t\t\treturn n, nil\n\t\t}\n","sourceCodeStart":51,"sourceCodeEnd":87,"githubUrl":"https://github.com/XTLS/Xray-core/blob/7d214f8b094f75322fa3990f8aadad1c912f24f5/transport/internet/finalmask/xmc/packet_stream.go#L51-L87","documentation":"packetStream.Read failed while framing the next Minecraft configuration packet from the underlying connection (readPacket). This wraps I/O errors (connection reset, EOF, deadline exceeded) and framing errors from the peer's byte stream, e.g. a Varint length prefix that is too large or a truncated packet body.","triggerScenarios":"Reading from an xmc packetStream after the peer closes or resets the TCP connection; peer sends malformed packet framing (oversized Varint, short body); connection deadline fires during a read.","commonSituations":"Real Minecraft server or middlebox rejects the camouflage stream and closes; NAT idle timeout kills the connection between keep-alives; protocol version drift makes the peer's packets unparseable; proxy chain (the actual tunnel payload) misbehaves.","solutions":["Check errors.Is(err, io.EOF) / errors.Is(err, net.ErrClosed) to distinguish clean close from corruption","Verify both endpoints run compatible xmc builds so packet IDs 0x01/0x02/0x04 and framing match","Ensure the server-side keep-alive loop is active so NAT mappings do not expire","Treat as fatal for the connection: tear down the wrapped net.Conn and reconnect at the application layer"],"exampleFix":"n, err := stream.Read(buf)\nif err != nil {\n    if errors.Is(err, io.EOF) || errors.Is(err, syscall.ECONNRESET) {\n        return handleDisconnect()\n    }\n    return fmt.Errorf(\"xmc stream failed: %w\", err)\n}","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"n, err := stream.Read(buf)\nif err != nil {\n    if errors.Is(err, io.EOF) || errors.Is(err, net.ErrClosed) {\n        // clean teardown path\n        return nil\n    }\n    return fmt.Errorf(\"xmc read: %w\", err)\n}","preventionTips":["Version-pin both endpoints so packet framing matches","Set read deadlines and close conns promptly to avoid ambiguous hangs","Distinguish EOF/reset from decode errors in logs to speed diagnosis"],"tags":["go","network","io","minecraft","framing"],"backgroundTag":null,"analyzedSha":"7d214f8b094f75322fa3990f8aadad1c912f24f5","analyzedAt":"2026-08-15T14:26:24.325Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}