{"record":{"id":"cd402697f9168a45","repo":"ginuerzh/gost","slug":"kcp-wrong-connection-type","errorCode":null,"errorMessage":"kcp: wrong connection type","messagePattern":"kcp: wrong connection type","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"error","filePath":"kcp.go","lineNumber":219,"sourceCode":"\t\t\treturn nil, err\n\t\t}\n\t\tsession = s\n\t\ttr.sessions[opts.Addr] = session\n\t}\n\tcc, err := session.GetConn()\n\tif err != nil {\n\t\tsession.Close()\n\t\tdelete(tr.sessions, opts.Addr)\n\t\treturn nil, err\n\t}\n\n\treturn cc, nil\n}\n\nfunc (tr *kcpTransporter) initSession(addr string, conn net.Conn, config *KCPConfig) (*muxSession, error) {\n\tpc, ok := conn.(net.PacketConn)\n\tif !ok {\n\t\treturn nil, errors.New(\"kcp: wrong connection type\")\n\t}\n\n\tkcpconn, err := kcp.NewConn(addr,\n\t\tblockCrypt(config.Key, config.Crypt, KCPSalt),\n\t\tconfig.DataShard, config.ParityShard, pc)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\tkcpconn.SetStreamMode(true)\n\tkcpconn.SetWriteDelay(false)\n\tkcpconn.SetNoDelay(config.NoDelay, config.Interval, config.Resend, config.NoCongestion)\n\tkcpconn.SetWindowSize(config.SndWnd, config.RcvWnd)\n\tkcpconn.SetMtu(config.MTU)\n\tkcpconn.SetACKNoDelay(config.AckNodelay)\n\n\tif config.DSCP > 0 {\n\t\tif err := kcpconn.SetDSCP(config.DSCP); err != nil {","sourceCodeStart":201,"sourceCodeEnd":237,"githubUrl":"https://github.com/ginuerzh/gost/blob/a33fdbf4c98034f4bfeeaea9868909822b9c526d/kcp.go#L201-L237","documentation":"kcpTransporter.initSession requires the conn it received to implement net.PacketConn, because the KCP protocol is built on top of UDP-style packet sockets. If the handed-over connection is a stream conn (e.g. *net.TCPConn or a wrapped/tunneled conn), it returns this error before creating the KCP session.","triggerScenarios":"Calling Handshake on the kcp transporter with a conn that is not a net.PacketConn — e.g. configuring the kcp transport but the dialer produced a stream connection, or passing a wrapped/muxed conn into initSession via Handshake.","commonSituations":"Misconfigured transport chain (kcp selected but underlying dialer is TCP); proxy chains wrapping conns so the concrete PacketConn type is lost; passing a net.Conn from another transport into the kcp handshake path.","solutions":["Ensure the kcp transport dials via its own UDP dialer so a net.PacketConn is passed to initSession.","Do not wrap the conn in intermediaries before kcp.Handshake; if wrapping is required, implement/unwrap to expose net.PacketConn.","Verify node/chain config so kcp:// URLs use the kcp dialer, not the tcp one.","If you must run KCP over a stream, use a KCP variant that supports stream conns instead of this transporter."],"exampleFix":"// before\nconn, _ := net.Dial(\"tcp\", addr) // stream conn\nsession, err := kcpTransporter.Handshake(conn, addr)\n// after\nconn, err := net.Dial(\"udp\", addr) // PacketConn\nsession, err := kcpTransporter.Handshake(conn, addr)","handlingStrategy":"validation","validationCode":"if _, ok := conn.(net.PacketConn); !ok {\n\treturn errors.New(\"kcp handshake requires a net.PacketConn (UDP) connection\")\n}","typeGuard":"func isPacketConn(c net.Conn) (net.PacketConn, bool) {\n\tpc, ok := c.(net.PacketConn)\n\treturn pc, ok\n}","tryCatchPattern":"session, err := tr.Handshake(conn, addr)\nif err != nil && strings.Contains(err.Error(), \"wrong connection type\") {\n\t// dial UDP and retry\n\tpc, derr := net.Dial(\"udp\", addr)\n\tif derr != nil { return derr }\n\tsession, err = tr.Handshake(pc, addr)\n}","preventionTips":["Always dial UDP when using the kcp transport; never feed TCP conns into it.","Avoid wrapping conns before kcp.Handshake so the concrete PacketConn type survives.","Validate transport/dialer pairing in config at startup."],"tags":["kcp","udp","type-assertion","transport"],"backgroundTag":"wrong-connection-type","analyzedSha":"a33fdbf4c98034f4bfeeaea9868909822b9c526d","analyzedAt":"2026-09-02T22:15:54.506Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-10T02:17:09.455Z"}