{"record":{"id":"8426730a18ab0204","repo":"fatedier/frp","slug":"initial-client-session-error-v","errorCode":null,"errorMessage":"initial client session error: %v","messagePattern":"initial client session error: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"client/visitor/xtcp.go","lineNumber":357,"sourceCode":"\tladdr, _ := net.ResolveUDPAddr(\"udp\", listenConn.LocalAddr().String())\n\tlConn, err := net.DialUDP(\"udp\", laddr, raddr)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"dial udp error: %v\", err)\n\t}\n\tremote, err := netpkg.NewKCPConnFromUDP(lConn, true, raddr.String())\n\tif err != nil {\n\t\tlConn.Close()\n\t\treturn fmt.Errorf(\"create kcp connection from udp connection error: %v\", err)\n\t}\n\n\tfmuxCfg := fmux.DefaultConfig()\n\tfmuxCfg.KeepAliveInterval = 10 * time.Second\n\tfmuxCfg.MaxStreamWindowSize = 6 * 1024 * 1024\n\tfmuxCfg.LogOutput = io.Discard\n\tsession, err := fmux.Client(remote, fmuxCfg)\n\tif err != nil {\n\t\tremote.Close()\n\t\treturn fmt.Errorf(\"initial client session error: %v\", err)\n\t}\n\tks.mu.Lock()\n\tks.session = session\n\tks.lConn = lConn\n\tks.mu.Unlock()\n\treturn nil\n}\n\nfunc (ks *KCPTunnelSession) OpenConn(_ context.Context) (net.Conn, error) {\n\tks.mu.RLock()\n\tdefer ks.mu.RUnlock()\n\tsession := ks.session\n\tif session == nil {\n\t\treturn nil, ErrNoTunnelSession\n\t}\n\treturn session.Open()\n}\n","sourceCodeStart":339,"sourceCodeEnd":375,"githubUrl":"https://github.com/fatedier/frp/blob/6c8a8d0a97d03b44e9528d30b30c70cb9d61b405/client/visitor/xtcp.go#L339-L375","documentation":"KCPTunnelSession.Init failed at fmux.Client(remote, fmuxCfg), creating the yamux-style multiplexed session over the freshly created KCP connection. With these configs (10 s keepalive, 6 MB window) the constructor rarely fails; an error means the multiplexer handshake over the KCP stream could not complete.","triggerScenarios":"fmux.Client returns an error when the initial handshake write/read over the KCP conn fails: the peer is not speaking fmux (version mismatch), the NAT hole actually closed, or the remote xtcp owner is not listening for KCP traffic on the punched mapping.","commonSituations":"frpc/frps version skew (fmux config incompatibility); hole punch succeeded at the STUN level but the data path is one-way (symmetric NAT on the peer); firewall dropping the larger initial frames (6 MB window advertisement).","solutions":["Confirm both endpoints run the same frp release; multiplexer handshake incompatibilities are the top cause.","Retest NAT behavior; if either side is symmetric NAT, xtcp will not converge, so use stcp instead.","Allow UDP in both directions for the data path, not just STUN.","Retry a few times; punched mappings are short-lived and the first attempt can race the mapping expiry."],"exampleFix":null,"handlingStrategy":"retry","validationCode":null,"typeGuard":null,"tryCatchPattern":null,"preventionTips":["Deploy identical frp versions on both xtcp peers","Ensure UDP is allowed in both directions for the data path","Retry the dial immediately; punched mappings expire fast"],"tags":["xtcp","kcp","multiplexing","version-mismatch"],"backgroundTag":null,"analyzedSha":"6c8a8d0a97d03b44e9528d30b30c70cb9d61b405","analyzedAt":"2026-08-15T06:53:27.215Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}