t8y2/dbx · error

ZooKeeper SASL response is truncated

Error message

ZooKeeper SASL response is truncated

What it means

zooKeeperSASLRound validates that a SASL response frame contains at least the 20-byte ZooKeeper response header (length, xid, zxid, error code). A shorter frame means the server sent a malformed or truncated response, so it cannot even be parsed for the error code.

Source

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

	}
	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 {
		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
}

View on GitHub (pinned to c0390bff16)

Solutions

  1. Check ZooKeeper server logs for connection resets or auth failures at the same time
  2. Verify the client is pointed at the correct ZooKeeper client port (default 2181) and not a proxy or admin port
  3. Retry the connection; transient truncation often indicates network interruption
  4. Upgrade driver/server if the server is an unusual build sending short SASL responses
Defensive patterns

Strategy: retry

Validate before calling

// Check connectivity before SASL: TCP dial + initial server handshake
c := net.DialTimeout("tcp", addr, 5*time.Second)
if c == nil { return errors.New("zookeeper unreachable") }

Try / catch

resp, err := zooKeeperSASLRound(conn, xid, token)
if err != nil {
    if strings.Contains(err.Error(), "truncated") {
        // reconnect with fresh xid and bounded retries
    }
    return err
}

Prevention

When it happens

Trigger: readZooKeeperFrame returns a response shorter than 20 bytes during the SASL negotiation round, e.g. when the server closes mid-frame or sends a non-SASL response.

Common situations: ZooKeeper server closing the connection abruptly, a proxy/load balancer cutting the stream, wrong port hitting a non-ZooKeeper service, or protocol version mismatches.

Related errors


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