t8y2/dbx · error

connect to ZooKeeper: %w

Error message

connect to ZooKeeper: %w

What it means

ZooKeeperDiscovery.Endpoints dials the ZooKeeper ensemble via the configured dialer and wraps any dial failure with this message. The %w preserves the underlying go-zookeeper error (refused, timeout, DNS failure). It is thrown before any session/auth work because no endpoint list can be read without a live connection.

Source

Thrown at agents/drivers/argo-go/discovery.go:106

				dialer := &net.Dialer{Timeout: dialTimeout}
				return tls.DialWithDialer(dialer, network, address, config)
			}),
		)
	}
}

func (discovery *zooKeeperDiscovery) Endpoints(ctx context.Context, rejected map[string]bool) ([]endpoint, error) {
	addresses := make([]string, 0, len(discovery.servers))
	for _, server := range discovery.servers {
		addresses = append(addresses, server.address())
	}
	timeout := discovery.timeout
	if timeout <= 0 {
		timeout = defaultConnectTimeout
	}
	connection, events, err := discovery.dialer(addresses, timeout)
	if err != nil {
		return nil, fmt.Errorf("connect to ZooKeeper: %w", err)
	}
	defer connection.Close()
	if err := waitForZooKeeperSession(ctx, events, timeout); err != nil {
		return nil, err
	}
	if discovery.authScheme != "" || discovery.auth != "" {
		if discovery.authScheme == "" || discovery.auth == "" {
			return nil, errors.New("ZooKeeper auth scheme and credentials must be configured together")
		}
		if err := connection.AddAuth(discovery.authScheme, []byte(discovery.auth)); err != nil {
			return nil, fmt.Errorf("authenticate to ZooKeeper: %w", err)
		}
	}
	resolved := make([]endpoint, 0)
	var listedPath string
	var nodeFailures []string
	for _, path := range discovery.paths() {
		children, _, childrenErr := connection.Children(path)

View on GitHub (pinned to c0390bff16)

Solutions

  1. Check the wrapped cause and verify ZooKeeper hosts/ports are correct and reachable
  2. Confirm the ZooKeeper ensemble is up (ruok/stat via four-letter words or zkCli)
  3. Increase the connect timeout if the ensemble is slow to accept
  4. Verify firewall/security-group and TLS dial configuration between client and ZK

Example fix

// before
dsn := "zookeeper://zk1.internal:2181/hs2"  // zk1 decommissioned
// after
dsn := "zookeeper://zk1.internal:2181,zk2.internal:2181,zk3.internal:2181/hs2"
Defensive patterns

Strategy: retry

Validate before calling

for _, hp := range strings.Split(zkHosts, ",") {
    conn, err := net.DialTimeout("tcp", hp, 3*time.Second)
    if err != nil {
        return fmt.Errorf("ZooKeeper %s unreachable: %w", hp, err)
    }
    conn.Close()
}

Try / catch

eps, err := discovery.Endpoints(ctx)
if err != nil {
    if strings.HasPrefix(err.Error(), "connect to ZooKeeper:") && errors.Is(err, context.DeadlineExceeded) {
        time.Sleep(2 * time.Second)
        eps, err = discovery.Endpoints(ctx) // retry with fresh session
    }
    if err != nil { return err }
}

Prevention

When it happens

Trigger: Calling Endpoints (via Hive discovery Connect) where discovery.dialer(addresses, timeout) fails: unreachable ZK hosts, connection timeout, TLS dial failure, DNS resolution failure.

Common situations: ZooKeeper ensemble down or in maintenance; wrong ZK host list/ports in the DSN; network partition or security-group rules; ZK client TLS endpoint used with plain dialer or vice versa; timeout too small for a loaded cluster.

Understand the failure class

Background: ECONNREFUSED and "connection refused" / "could not connect to server" errors: what they mean and how to fix them — this error's family across 44 libraries.

Related errors


AI-assisted analysis of t8y2/dbx@c0390bff16 (2026-09-05). Data as JSON: /api/errors/c9825fe29f2f94d2. Report an issue: GitHub.