snail007/goproxy · error

write connection data err: %s ,retrying...

Error message

write connection data err: %s ,retrying...

What it means

After GetConn succeeds, GetInConn writes a handshake packet (type, key length, key) to the new connection. This error is thrown when that write fails; the connection is closed immediately so the caller can retry, as the message says.

Source

Thrown at services/tunnel_client.go:94

}
func (s *TunnelClient) Clean() {
	s.StopService()
}
func (s *TunnelClient) GetInConn(typ uint8) (outConn net.Conn, err error) {
	outConn, err = s.GetConn()
	if err != nil {
		err = fmt.Errorf("connection err: %s", err)
		return
	}
	keyBytes := []byte(*s.cfg.Key)
	keyLength := uint16(len(keyBytes))
	pkg := new(bytes.Buffer)
	binary.Write(pkg, binary.LittleEndian, typ)
	binary.Write(pkg, binary.LittleEndian, keyLength)
	binary.Write(pkg, binary.LittleEndian, keyBytes)
	_, err = outConn.Write(pkg.Bytes())
	if err != nil {
		err = fmt.Errorf("write connection data err: %s ,retrying...", err)
		utils.CloseConn(&outConn)
		return
	}
	return
}
func (s *TunnelClient) GetConn() (conn net.Conn, err error) {
	var _conn tls.Conn
	_conn, err = utils.TlsConnectHost(*s.cfg.Parent, *s.cfg.Timeout, s.cfg.CertBytes, s.cfg.KeyBytes)
	if err == nil {
		conn = net.Conn(&_conn)
	}
	return
}
func (s *TunnelClient) ServeUDP() {
	var inConn net.Conn
	var err error
	for {
		for {

View on GitHub (pinned to e6d6a821db)

Solutions

  1. Confirm the client key (cfg.Key) matches the server's key, since the server may drop conns on bad keys
  2. Retry the operation — the code already closes the conn and the message indicates retrying; add backoff in your wrapper
  3. Check server-side logs at the same timestamp for why the server closed the accepted connection
  4. Stabilize the network path (keep-alives, TCP keepalive settings) if running over flaky links

Example fix

// before: fire-and-forget single attempt
conn, err := client.GetInConn(typ)
// after: retry with backoff
var conn net.Conn
for i := 0; i < 3; i++ {
    conn, err = client.GetInConn(typ)
    if err == nil { break }
    time.Sleep(time.Duration(1<<i) * time.Second)
}
Defensive patterns

Strategy: retry

Validate before calling

// verify key length is sane and matches server expectation before writing
if len(cfg.Key) == 0 || len(cfg.Key) > 65535 {
    return errors.New("tunnel key must be non-empty and <64KB")
}

Try / catch

conn, err := client.GetInConn(typ)
if err != nil && strings.Contains(err.Error(), "write connection data err") {
    time.Sleep(backoff) // conn already closed by lib; just retry
    conn, err = client.GetInConn(typ)
}

Prevention

When it happens

Trigger: outConn.Write(pkg.Bytes()) fails after the connection was established — typically because the server closed the conn right after accept (auth/key rejected, TLS failure, server restarting) or the network dropped mid-write; GetInConn closes outConn and returns the wrapped error.

Common situations: Mismatched client key so the server drops the connection; server restarted between accept and read; intermediate proxy/firewall RSTs the connection; unstable mobile/VPN network dropping packets.

Related errors


AI-assisted analysis of snail007/goproxy@e6d6a821db (2026-09-03). Data as JSON: /api/errors/8fd8eecfc0075df6. Report an issue: GitHub.