t8y2/dbx · error

ZooKeeper SASL server returned error %d

Error message

ZooKeeper SASL server returned error %d

What it means

After XID validation, zooKeeperSASLRound reads bytes 16:20 as the server's error code. A nonzero code means the ZooKeeper server rejected the SASL operation for that round, and the code is surfaced in this error. This is the standard path by which authentication rejections (bad credentials) are reported.

Source

Thrown at agents/drivers/zookeeper/sasl.go:141

	binary.BigEndian.PutUint32(payload[8:12], uint32(len(token)))
	copy(payload[12:], token)
	if err := writeZooKeeperFrame(connection, payload); err != nil {
		return nil, err
	}
	response, err := readZooKeeperFrame(connection)
	if err != nil {
		return nil, err
	}
	if len(response) < 20 {
		return nil, errors.New("ZooKeeper SASL response is truncated")
	}
	responseXID := int32(binary.BigEndian.Uint32(response[4:8]))
	if responseXID != xid {
		return nil, fmt.Errorf("ZooKeeper SASL response xid %d does not match request xid %d", responseXID, xid)
	}
	errorCode := int32(binary.BigEndian.Uint32(response[16:20]))
	if errorCode != 0 {
		return nil, fmt.Errorf("ZooKeeper SASL server returned error %d", errorCode)
	}
	if len(response) < 24 {
		return nil, errors.New("ZooKeeper SASL token is truncated")
	}
	tokenLength := int(int32(binary.BigEndian.Uint32(response[20:24])))
	if tokenLength < 0 || tokenLength > zooKeeperMaximumFrameLen || 24+tokenLength > len(response) {
		return nil, fmt.Errorf("ZooKeeper SASL token length %d is invalid", tokenLength)
	}
	return append([]byte(nil), response[24:24+tokenLength]...), nil
}

func readZooKeeperFrame(reader io.Reader) ([]byte, error) {
	header := make([]byte, 4)
	if _, err := io.ReadFull(reader, header); err != nil {
		return nil, err
	}
	length := int(int32(binary.BigEndian.Uint32(header)))
	if length < 0 || length > zooKeeperMaximumFrameLen {

View on GitHub (pinned to c0390bff16)

Solutions

  1. Verify the digest username/password against the server's credential store (digest auth line in JAAS/zoo.cfg).
  2. Check server logs for the matching SASL/authentication failure to see the exact ZooKeeper error code.
  3. Confirm the server's authProvider includes the digest provider and the JAAS Server section is correct.
  4. Fix credentials and retry authenticateSASLDigest.

Example fix

// before
opts := Options{SASL: true, SASLUser: "admin", SASLPassword: "wrong"}
// after
opts := Options{SASL: true, SASLUser: "admin", SASLPassword: "correct-secret"}
Defensive patterns

Strategy: retry

Validate before calling

if creds.User == "" || creds.Password == "" { return errors.New("SASL credentials must be set") }

Try / catch

_, err := zooKeeperSASLRound(conn, xid, token)
if err != nil && strings.Contains(err.Error(), "server returned error") {
	// Extract code, do not blindly retry auth failures
	return classifyAuthFailure(err) // retry only for transient codes
}

Prevention

When it happens

Trigger: zooKeeperSASLRound receives a well-framed response whose errorCode field is nonzero — e.g. the server rejects the DIGEST-MD5 credentials or the SASL session state.

Common situations: Wrong username/password against a ZooKeeper with DigestAuthenticationProvider, server configured to require SASL while the client sent invalid auth, or server-side JAAS misconfiguration.

Related errors


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