t8y2/dbx · error
send ZooKeeper connect request: %w
Error message
send ZooKeeper connect request: %w
What it means
newProtocolZooKeeperClient builds the ZooKeeper connect request and writes it as a single frame with writeFrame; if the write fails (connection broken, closed, timed out) the error is wrapped as 'send ZooKeeper connect request'. This happens after the TCP/TLS connection succeeded but before any server response, indicating a transport-level problem during handshake.
Source
Thrown at agents/drivers/argo-go/zookeeper_protocol.go:156
closed bool
}
func newProtocolZooKeeperClient(connection net.Conn, timeout time.Duration) (*protocolZooKeeperClient, error) {
if connection == nil {
return nil, errors.New("ZooKeeper connection is nil")
}
if timeout <= 0 {
timeout = defaultConnectTimeout
}
client := &protocolZooKeeperClient{connection: connection, timeout: timeout}
request := &zooKeeperEncoder{}
request.int32(zooKeeperProtocolVersion)
request.int64(0)
request.int32(zooKeeperTimeoutMillis(timeout))
request.int64(0)
request.bytes(make([]byte, 16))
if err := client.writeFrame(request.data()); err != nil {
return nil, fmt.Errorf("send ZooKeeper connect request: %w", err)
}
response, err := client.readFrame()
if err != nil {
return nil, fmt.Errorf("read ZooKeeper connect response: %w", err)
}
decoder := newZooKeeperDecoder(response)
if _, err := decoder.int32(); err != nil {
return nil, fmt.Errorf("decode ZooKeeper protocol version: %w", err)
}
if _, err := decoder.int32(); err != nil {
return nil, fmt.Errorf("decode ZooKeeper session timeout: %w", err)
}
sessionID, err := decoder.int64()
if err != nil {
return nil, fmt.Errorf("decode ZooKeeper session ID: %w", err)
}
if _, err := decoder.bytes(); err != nil {
return nil, fmt.Errorf("decode ZooKeeper session password: %w", err)View on GitHub (pinned to c0390bff16)
Solutions
- Check connectivity to the ZooKeeper host:port and any load balancer/idle-timeout in front of it
- Ensure the ZooKeeper server is up and accepting connections (server log, 4lw 'ruok' command)
- Increase the dial/session timeout if writes time out on slow links
- Retry the connection — connectKerberosZooKeeper will fail over to the next ensemble member
Defensive patterns
Strategy: retry
Validate before calling
conn, err := net.DialTimeout("tcp", address, 5*time.Second)
if err != nil { return err }
conn.Close() // reachability pre-check before the protocol handshake Try / catch
client, err := newProtocolZooKeeperClient(conn, timeout)
if err != nil {
if errors.Is(err, syscall.ECONNRESET) || isTimeout(err) {
return retryWithBackoff(3, func() error { return dialAndConnect(address) })
}
return err
} Prevention
- Tune load-balancer/idle timeouts to exceed session negotiation time
- Set sane dial/write deadlines and retry transient IO errors with backoff
- Monitor ZooKeeper server logs for dropped client connections
- Fail over to the next ensemble member on send failures
When it happens
Trigger: Calling connectKerberosZooKeeper (which invokes newProtocolZooKeeperClient) where the underlying net.Conn write of the connect frame fails: server closed the connection immediately after accept, network timeout mid-write, or TLS handshake accepted but peer reset the stream.
Common situations: ZooKeeper listener closed by a load balancer idle timeout; packet loss on the way to the ensemble; server crash between TCP accept and protocol read; Docker/K8s sidecar terminating the connection before the first frame.
Related errors
- ZooKeeper SASL response is truncated
- read ZooKeeper connect response: %w
- ZooKeeper connection timed out before a session was establis
- ZooKeeper session expired during connection
- ZooKeeper sent an unexpected token after GSSAPI completion
AI-assisted analysis of t8y2/dbx@c0390bff16 (2026-09-05).
Data as JSON: /api/errors/22a6c7f5da5029e5.
Report an issue: GitHub.