fatedier/frp · warning

create tls config error

Error message

create tls config error: %v

What it means

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.

Solutions

  1. If you see this error you are running modified code; diff pkg/transport/tls.go and client/visitor/xtcp.go against upstream.
  2. For upstream frp, treat this error as a signal of binary divergence: reinstall matching frpc/frps releases.
  3. File an upstream issue; the branch indicates API drift between caller and helper.
Defensive patterns

Strategy: try-catch

Try / catch

if err := qs.Init(conn, raddr); err != nil {
    if strings.Contains(err.Error(), "create tls config") {
        // unreachable in upstream: indicates fork/version drift — verify binary provenance
    }
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Understand the failure class

Related errors


AI-assisted analysis of fatedier/frp@6c8a8d0a97 (2026-08-15). Data as JSON: /api/errors/b55f3be8a6f2bb0b. Report an issue: GitHub.

Appendix: source

Thrown at client/visitor/xtcp.go:406

type QUICTunnelSession struct {
	session    *quic.Conn
	listenConn *net.UDPConn
	mu         sync.RWMutex

	clientCfg *v1.ClientCommonConfig
}

func NewQUICTunnelSession(clientCfg *v1.ClientCommonConfig) TunnelSession {
	return &QUICTunnelSession{
		clientCfg: clientCfg,
	}
}

func (qs *QUICTunnelSession) Init(listenConn *net.UDPConn, raddr *net.UDPAddr) error {
	tlsConfig, err := transport.NewClientTLSConfig("", "", "", raddr.String())
	if err != nil {
		return fmt.Errorf("create tls config error: %v", err)
	}
	tlsConfig.NextProtos = []string{"frp"}
	quicConn, err := quic.Dial(context.Background(), listenConn, raddr, tlsConfig,
		&quic.Config{
			MaxIdleTimeout:     time.Duration(qs.clientCfg.Transport.QUIC.MaxIdleTimeout) * time.Second,
			MaxIncomingStreams: int64(qs.clientCfg.Transport.QUIC.MaxIncomingStreams),
			KeepAlivePeriod:    time.Duration(qs.clientCfg.Transport.QUIC.KeepalivePeriod) * time.Second,
		})
	if err != nil {
		return fmt.Errorf("dial quic error: %v", err)
	}
	qs.mu.Lock()
	qs.session = quicConn
	qs.listenConn = listenConn
	qs.mu.Unlock()
	return nil
}

View on GitHub (pinned to 6c8a8d0a97)