t8y2/dbx · error
ZooKeeper SASL round %d: %w
Error message
ZooKeeper SASL round %d: %w
What it means
This error wraps any failure that occurs while sending or receiving a ZooKeeper SASL (GSSAPI/Kerberos) round-trip during authentication. authenticateSASL sends each GSSAPI token via a SASL opcode request; if the underlying request fails (I/O error, timeout, protocol error, auth failure), it is wrapped with the SASL round number so the failing negotiation step is identifiable. It indicates the client never got a usable challenge/response for that round.
Source
Thrown at agents/drivers/argo-go/zookeeper_protocol.go:211
func (client *protocolZooKeeperClient) authenticateSASL(saslClient zooKeeperSASLClient) error {
if saslClient == nil {
return errors.New("ZooKeeper SASL client is nil")
}
defer saslClient.Dispose()
token, err := saslClient.Start()
if err != nil {
return fmt.Errorf("start ZooKeeper GSSAPI negotiation: %w", err)
}
for round := 0; round < zooKeeperMaxSASLRounds; round++ {
response, requestErr := client.request(zooKeeperOpSASL, func(encoder *zooKeeperEncoder) {
if token == nil {
encoder.bytes([]byte{})
return
}
encoder.bytes(token)
})
if requestErr != nil {
return fmt.Errorf("ZooKeeper SASL round %d: %w", round+1, requestErr)
}
decoder := newZooKeeperDecoder(response)
challenge, decodeErr := decoder.bytes()
if decodeErr != nil {
return fmt.Errorf("decode ZooKeeper SASL round %d: %w", round+1, decodeErr)
}
if saslClient.Complete() {
if len(challenge) != 0 {
return errors.New("ZooKeeper sent an unexpected token after GSSAPI completion")
}
return nil
}
token, err = saslClient.Step(challenge)
if err != nil {
return fmt.Errorf("continue ZooKeeper GSSAPI negotiation at round %d: %w", round+1, err)
}
}
return fmt.Errorf("ZooKeeper GSSAPI negotiation exceeded %d rounds", zooKeeperMaxSASLRounds)View on GitHub (pinned to c0390bff16)
Solutions
- Verify the Kerberos environment on the client host: run kinit with the correct principal and confirm the ticket is valid (klist) before connecting.
- Check the ZooKeeper server is configured for SASL (authProvider, jaas.conf) and the client principal is allowed by the server ACL; inspect the server log for the matching auth failure.
- Increase the client timeout passed to the ZooKeeper connection so SASL/KDC round-trips are not cut off by the read/write deadline.
- Test network reachability to the ZooKeeper quorum (the error wraps raw I/O errors; connection resets indicate firewall/proxy drops).
- Inspect the wrapped inner error (%w) to distinguish transport failure from a server-returned ZooKeeper error code.
Example fix
// before: SASL fails due to missing ticket client, err := zookeeper.Connect(hosts, timeout) // SASL round 1: read tcp ...: connection reset // after: kinit first and verify $ kinit -kt /etc/security/keytabs/zk.service.keytab zookeeper/host@REALM && klist client, err := zookeeper.Connect(hosts, timeout)
Defensive patterns
Strategy: retry
Validate before calling
// Validate Kerberos environment before connecting
out, err := exec.Command("klist", "-s").Output()
if err != nil {
return fmt.Errorf("no valid Kerberos ticket; run kinit before connecting: %w", err)
}
conn, err := net.DialTimeout("tcp", host, 5*time.Second)
if err != nil {
return fmt.Errorf("ZooKeeper host unreachable: %w", err)
}
conn.Close() Try / catch
if err := client.Connect(); err != nil {
var saslErr error
if strings.Contains(err.Error(), "ZooKeeper SASL round") && errors.As(err, &saslErr) {
if isRetryable(err) { // transport timeout/reset, not auth rejection
time.Sleep(backoff)
return retryConnect()
}
}
return fmt.Errorf("zookeeper connect failed: %w", err)
} Prevention
- Run a scheduled kinit (or use a keytab with kinit -kt) so tickets never expire while the process runs.
- Verify the ZooKeeper server's SASL/JAAS configuration before deploying the client.
- Set the connection timeout generously enough to cover multiple KDC round-trips.
- Confirm network paths and firewall rules to port 2181 allow sustained TCP sessions.
When it happens
Trigger: Calling any ZooKeeper operation that triggers authenticateSASL (connection setup with a SASL/GSSAPI client) where client.request(zooKeeperOpSASL, ...) returns an error on a given round: TCP write/read failure, read/write deadline (client.timeout) exceeded, server closing the connection mid-negotiation, or a ZooKeeper error code returned in the response (e.g. auth failure).
Common situations: Kerberos environment misconfiguration (missing/invalid keytab, wrong principal, stale ticket cache, KDC unreachable), ZooKeeper server rejecting the SASL token (server not configured with quorum.auth/sasl enabled), network/firewall dropping the connection mid-handshake, or timeouts set too low for the KDC round-trips.
Related errors
- ZooKeeper session closed because SASL authentication is requ
- continue ZooKeeper GSSAPI negotiation at round %d: %w
- ZooKeeper Kerberos SASL requires Hive Kerberos credentials
- ZooKeeper SASL client is nil
- ZooKeeper session closed because SASL authentication is requ
AI-assisted analysis of t8y2/dbx@c0390bff16 (2026-09-05).
Data as JSON: /api/errors/7ba541751ea481de.
Report an issue: GitHub.