t8y2/dbx · error

ZooKeeper server list is empty

Error message

ZooKeeper server list is empty

What it means

connectKerberosZooKeeper validates the server list up front and returns this error when the servers slice has zero entries. Establishing a ZooKeeper connection is impossible without at least one host:port, so the library fails fast before attempting Kerberos setup or shuffling.

Source

Thrown at agents/drivers/argo-go/zookeeper_protocol.go:93

	options.QOP = "auth"
	options.AuthorizationID = ""
	options.ServiceHost = ""
	options.CanonicalizeHost = config.ZooKeeperKerberos.CanonicalHostname
	options.ServerName = config.ZooKeeperKerberos.ServerPrincipal
	if options.ServerName == "" && config.ZooKeeperKerberos.Realm != "" {
		options.ServerName = service + "/_HOST@" + config.ZooKeeperKerberos.Realm
	}
	return service, options
}

func connectKerberosZooKeeper(
	servers []string,
	timeout time.Duration,
	tlsConfig *tls.Config,
	config connectionConfig,
) (zooKeeperClient, <-chan zk.Event, error) {
	if len(servers) == 0 {
		return nil, nil, errors.New("ZooKeeper server list is empty")
	}
	if !config.Kerberos.Enabled {
		return nil, nil, errors.New("ZooKeeper Kerberos SASL requires Hive Kerberos credentials")
	}
	ordered := append([]string(nil), servers...)
	shuffleZooKeeperServers(ordered)
	var failures []string
	for _, address := range ordered {
		host, _, err := net.SplitHostPort(address)
		if err != nil {
			failures = append(failures, fmt.Sprintf("%s: %v", address, err))
			continue
		}
		connection, err := dialZooKeeperConnection(address, timeout, tlsConfig)
		if err != nil {
			failures = append(failures, fmt.Sprintf("%s: %v", address, err))
			continue
		}

View on GitHub (pinned to c0390bff16)

Solutions

  1. Populate the ZooKeeper server list (host:port[,host:port...]) in the connection config
  2. Validate at startup that the parsed server list is non-empty and fail with an application-level message
  3. Fix the config/env parsing that produced an empty list (trim, handle missing env vars)
  4. Point to reachable ensemble members if hosts were intentionally left blank in dev

Example fix

// before
conn, _, err := connectKerberosZooKeeper(strings.Split(os.Getenv("ZK_QUORUM"), ","), timeout, tls, cfg)
// after
raw := strings.TrimSpace(os.Getenv("ZK_QUORUM"))
if raw == "" {
    return fmt.Errorf("ZK_QUORUM is required")
}
conn, _, err := connectKerberosZooKeeper(strings.Split(raw, ","), timeout, tls, cfg)
Defensive patterns

Strategy: validation

Validate before calling

servers := strings.Split(strings.TrimSpace(cfg.ZooKeeperQuorum), ",")
if len(servers) == 0 || (len(servers) == 1 && servers[0] == "") {
    return errors.New("zookeeper quorum must list at least one host:port")
}

Try / catch

conn, events, err := connectKerberosZooKeeper(servers, timeout, tls, cfg)
if err != nil && strings.Contains(err.Error(), "ZooKeeper server list is empty") {
    // fail startup with a clear config error
}

Prevention

When it happens

Trigger: Calling connectKerberosZooKeeper (or the connect path it backs) with servers == nil or an empty slice — typically from an empty/whitespace-only zookeeper.quorum config or a config parse that produced no hosts.

Common situations: Config file missing the ZooKeeper hosts key; environment variable like ZOOKEEPER_QUORUM unset or empty; splitting a comma-separated quorum string that was empty resulting in a zero-length slice.

Understand the failure class

Background: "environment variable is not set" and "Missing keys in environment" errors: what missing required env var messages mean and how to fix them — this error's family across 28 libraries.

Related errors


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