{"record":{"id":"b55f3be8a6f2bb0b","repo":"fatedier/frp","slug":"create-tls-config-error-v","errorCode":null,"errorMessage":"create tls config error: %v","messagePattern":"create tls config error: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"client/visitor/xtcp.go","lineNumber":406,"sourceCode":"\ntype QUICTunnelSession struct {\n\tsession    *quic.Conn\n\tlistenConn *net.UDPConn\n\tmu         sync.RWMutex\n\n\tclientCfg *v1.ClientCommonConfig\n}\n\nfunc NewQUICTunnelSession(clientCfg *v1.ClientCommonConfig) TunnelSession {\n\treturn &QUICTunnelSession{\n\t\tclientCfg: clientCfg,\n\t}\n}\n\nfunc (qs *QUICTunnelSession) Init(listenConn *net.UDPConn, raddr *net.UDPAddr) error {\n\ttlsConfig, err := transport.NewClientTLSConfig(\"\", \"\", \"\", raddr.String())\n\tif err != nil {\n\t\treturn fmt.Errorf(\"create tls config error: %v\", err)\n\t}\n\ttlsConfig.NextProtos = []string{\"frp\"}\n\tquicConn, err := quic.Dial(context.Background(), listenConn, raddr, tlsConfig,\n\t\t&quic.Config{\n\t\t\tMaxIdleTimeout:     time.Duration(qs.clientCfg.Transport.QUIC.MaxIdleTimeout) * time.Second,\n\t\t\tMaxIncomingStreams: int64(qs.clientCfg.Transport.QUIC.MaxIncomingStreams),\n\t\t\tKeepAlivePeriod:    time.Duration(qs.clientCfg.Transport.QUIC.KeepalivePeriod) * time.Second,\n\t\t})\n\tif err != nil {\n\t\treturn fmt.Errorf(\"dial quic error: %v\", err)\n\t}\n\tqs.mu.Lock()\n\tqs.session = quicConn\n\tqs.listenConn = listenConn\n\tqs.mu.Unlock()\n\treturn nil\n}\n","sourceCodeStart":388,"sourceCodeEnd":424,"githubUrl":"https://github.com/fatedier/frp/blob/6c8a8d0a97d03b44e9528d30b30c70cb9d61b405/client/visitor/xtcp.go#L388-L424","documentation":"QUICTunnelSession.Init failed to build the TLS config used for the QUIC dial via transport.NewClientTLSConfig(\"\", \"\", \"\", raddr.String()). Inspecting that helper: with all file paths empty it only sets ServerName and InsecureSkipVerify, which cannot fail, so in current upstream code this branch is effectively unreachable.","triggerScenarios":"NewClientTLSConfig errors only when certPath/keyPath/caPath are non-empty and loading/parsing fails; this caller hardcodes empty strings, so the branch is dead code in practice today.","commonSituations":"Hitting this message would require a future code change passing TLS file paths here, or a fork that adds validation to the empty-path case.","solutions":["If you see this error you are running modified code; diff pkg/transport/tls.go and client/visitor/xtcp.go against upstream.","For upstream frp, treat this error as a signal of binary divergence: reinstall matching frpc/frps releases.","File an upstream issue; the branch indicates API drift between caller and helper."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"if err := qs.Init(conn, raddr); err != nil {\n    if strings.Contains(err.Error(), \"create tls config\") {\n        // unreachable in upstream: indicates fork/version drift — verify binary provenance\n    }\n}","preventionTips":["Install frpc/frps from official releases so caller and TLS helper stay in sync","Treat this error as a canary for modified builds"],"tags":["xtcp","quic","tls","dead-code"],"backgroundTag":null,"analyzedSha":"6c8a8d0a97d03b44e9528d30b30c70cb9d61b405","analyzedAt":"2026-08-15T06:53:27.215Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}