t8y2/dbx · error
continue ZooKeeper DIGEST-MD5 negotiation at round %d: %w
Error message
continue ZooKeeper DIGEST-MD5 negotiation at round %d: %w
What it means
After receiving a challenge, the client calls saslClient.Step(challenge) to compute the next response. If Step rejects the challenge (malformed rspauth, protocol violation, wrong credentials), the error is wrapped as "continue ZooKeeper DIGEST-MD5 negotiation at round %d: %w". This is a client-side cryptographic/protocol rejection, not a network error.
Source
Thrown at agents/drivers/zookeeper/sasl.go:107
token, err := saslClient.Start()
if err != nil {
return fmt.Errorf("start ZooKeeper DIGEST-MD5 negotiation: %w", err)
}
for round := 0; round < zooKeeperSASLMaxRounds; round++ {
challenge, err := zooKeeperSASLRound(connection, zooKeeperSASLXIDBase+int32(round), token)
if err != nil {
return fmt.Errorf("ZooKeeper SASL round %d: %w", round+1, err)
}
if saslClient.Complete() {
if len(challenge) != 0 {
return errors.New("ZooKeeper sent an unexpected token after DIGEST-MD5 completion")
}
return nil
}
token, err = saslClient.Step(challenge)
if err != nil {
return fmt.Errorf("continue ZooKeeper DIGEST-MD5 negotiation at round %d: %w", round+1, err)
}
if saslClient.Complete() {
if len(token) != 0 {
return errors.New("ZooKeeper DIGEST-MD5 completed with an unexpected client token")
}
return nil
}
}
return fmt.Errorf("ZooKeeper DIGEST-MD5 negotiation exceeded %d rounds", zooKeeperSASLMaxRounds)
}
func zooKeeperSASLRound(connection net.Conn, xid int32, token []byte) ([]byte, error) {
payload := make([]byte, 12+len(token))
binary.BigEndian.PutUint32(payload[0:4], uint32(xid))
binary.BigEndian.PutUint32(payload[4:8], uint32(zooKeeperSASLOpcode))
binary.BigEndian.PutUint32(payload[8:12], uint32(len(token)))
copy(payload[12:], token)
if err := writeZooKeeperFrame(connection, payload); err != nil {View on GitHub (pinned to c0390bff16)
Solutions
- Re-check the digest username/password — bad credentials most commonly make Step fail.
- Compare qop/realm/cipher settings negotiated with the server's SASL configuration.
- Look at the wrapped inner error for the precise Step failure reason.
- Ensure both client and server use standard DIGEST-MD5 semantics; upgrade the SASL client library if it deviates.
Defensive patterns
Strategy: validation
Validate before calling
// Verify credentials before starting; bad secrets are the most common Step() failure.
if creds.User == "" || creds.Password == "" { return errors.New("empty SASL credentials") } Try / catch
err := negotiateSASLDigest(conn, creds)
if err != nil && strings.Contains(err.Error(), "continue ZooKeeper DIGEST-MD5 negotiation") {
return fmt.Errorf("check DIGEST-MD5 credentials/qop settings: %w", err)
} Prevention
- Double-check digest username/password before enabling SASL.
- Match qop/realm/cipher settings with the server's JAAS configuration.
- Test the same credentials with zkCli.sh digest auth to validate them independently.
When it happens
Trigger: negotiateSASLDigest's loop calls saslClient.Step(challenge) at round N and Step returns an error, typically because the server's challenge is not a valid DIGEST-MD5 response for the given credentials.
Common situations: Wrong username/password (the server's rspauth check fails), server using a different qop/realm configuration than the client expects, or an incompatible SASL implementation on one side.
Related errors
- start ZooKeeper DIGEST-MD5 negotiation: %w
- ZooKeeper session closed because SASL authentication is requ
- ZooKeeper authentication failed
- ZooKeeper session closed because SASL authentication is requ
- username is required when auth_scheme = "sasl_digest"
AI-assisted analysis of t8y2/dbx@c0390bff16 (2026-09-05).
Data as JSON: /api/errors/0bcdbf3c04052151.
Report an issue: GitHub.