diff --git a/daemon/src/blue_daemon.cpp b/daemon/src/blue_daemon.cpp
index f11aea4851ef9d472cb88dbd4bf8103cf2198456..730e81dc49eda23852cc537632059ecea0504f5b 100644
--- a/daemon/src/blue_daemon.cpp
+++ b/daemon/src/blue_daemon.cpp
@@ -405,7 +405,7 @@ blue::rpc_op blue_daemon::set_pin_request(const blue::bdaddr &addr,
 
 		ret = blue::rpc_op::OP_DEVICE_PIN_DONE;
 	}
-	catch (const std::length_error &)
+	catch (const std::runtime_error &)
 	{
 		ret = blue::rpc_op::OP_DEVICE_PIN_TOO_LONG;
 	}
diff --git a/lib/include/bdaddr.h b/lib/include/bdaddr.h
index 1e700bffe6cc20c2b055c49ee2d2d532c1cd2dc8..3eecf2a7238892a8cc69e462dd0624de323ffecd 100644
--- a/lib/include/bdaddr.h
+++ b/lib/include/bdaddr.h
@@ -33,6 +33,8 @@ public:
 
 	/*
 	 * Wrap the C type bdaddr_t in class bdaddr. addr is copied.
+	 *
+	 * throws std::runtime_error() on format error
 	 */
 	bdaddr(bdaddr_t addr);
 
diff --git a/lib/include/btdevice.h b/lib/include/btdevice.h
index 2c33f2c0634449757334a87d24a813773b339c56..09ac4da2efe7c311a56f7baae6d57a6087b1af01 100644
--- a/lib/include/btdevice.h
+++ b/lib/include/btdevice.h
@@ -150,7 +150,7 @@ public:
 	 * Set the pin code for the device.
 	 *
 	 * The PIN must be shorter than NG_HCI_PIN_SIZE, a
-	 * std::length_error is thrown if the provided PIN is too long.
+	 * std::runtime_error() is thrown if the provided PIN is too long.
 	 */
 	void set_pin(std::string pin);
 
@@ -167,11 +167,15 @@ public:
 	/*
 	 * Send a bluetooth authentication request to the device.
 	 * Typically handled internally during pairing.
+	 *
+	 * throws std::runtime_error() on error
 	 */
 	void send_auth_req();
 	/*
 	 * Enable encryption for the connection to the device.
 	 * Typically handled internally during pairing.
+	 *
+	 * throws std::runtime_error() on error
 	 */
 	void enable_encryption();
 	/*
@@ -182,6 +186,9 @@ public:
 	 * Return
 	 * 	true  - pairing started
 	 * 	false - device is already paired
+	 *
+	 * 	throws std::runtime_error() if the device is busy or the
+	 * 	operation fails to start
 	 */
 	bool pair();
 	/*
@@ -189,6 +196,8 @@ public:
 	 * in device_observer::remote_name() being called upon completion.
 	 * On success the name can be retrieved by calling
 	 * btdevice::get_name().
+	 *
+	 * throws std::runtime_error() on error
 	 */
 	void request_name();
 	/*
diff --git a/lib/include/hci_socket.h b/lib/include/hci_socket.h
index d9de97d21078680a68c6f217424ffb971351217e..371e943e827e4374919137645b5aa3ecc5428bb8 100644
--- a/lib/include/hci_socket.h
+++ b/lib/include/hci_socket.h
@@ -201,6 +201,12 @@ public:
 		std::string msg;
 	};
 
+	/*
+	 * Contruct a HCI socket processing IO events from the main loop
+	 * passed in loop.
+	 *
+	 * throws std::runtime_error() on error
+	 */
 	hci_socket(ev::loop_ref loop);
 	~hci_socket() = default;
 
@@ -217,10 +223,14 @@ public:
 
 	/*
 	 * Bind the HCI socket to a bluetooth ubt node.
+	 *
+	 * thows std::runtime_error() on error
 	 */
 	void bind(const std::string &node);
 	/*
 	 * Connect the HCI socket to a bluetooth ubt node.
+	 *
+	 * throws std::runtime_error() on error
 	 */
 	void connect(const std::string &node);
 	/*
@@ -232,6 +242,8 @@ public:
 	 * blue::hci_socket qs;
 	 * qs.bind("hci0ubt");
 	 * nodes = qs.find_hci_nodes();
+	 *
+	 * throws std::runtime_error() on error
 	 */
 	std::vector<nodeinfo> find_hci_nodes();
 
@@ -248,6 +260,8 @@ public:
 	 *
 	 * socket->send(NG_HCI_OPCODE(NG_HCI_OGF_LINK_CONTROL, NG_HCI_OCF_AUTH_REQ),
 	 *		cp);
+	 *
+	 * throws std::runtime_error() on error
 	 */
 	template<class T>
 	void send(uint16_t opcode, T cp);
@@ -277,6 +291,8 @@ public:
 	 * Scan for discoverable devices on the bluetooth network.
 	 * Generates a NG_HCI_EVENT_INQUIRY_COMPL event on completion and
 	 * found devices can be retrieved by calling get_devices().
+	 *
+	 * throws std::runtime_error() on error
 	 */
 	void query_devices();
 
diff --git a/lib/include/hid/bthid.h b/lib/include/hid/bthid.h
index ccf2482c31cd005dcbd0917594de0a1536dcc4c1..dba85acdf5938c7566c56ab49cf7ebee92ee4e08 100644
--- a/lib/include/hid/bthid.h
+++ b/lib/include/hid/bthid.h
@@ -98,8 +98,6 @@ namespace blue::hid
 	std::optional<device_id> get_devid(util::shared_cap_chan sdp_chan,
 			blue::bdaddr addr);
 
-	int32_t process_hid_descriptor(hid_descriptor &d);
-
 } // namespace blue::bthid
 
 #endif // BTHID_H
diff --git a/lib/include/hid/hid_device.h b/lib/include/hid/hid_device.h
index 8f723ead0b4b73cdacfb2c2da4f7a1ef204dbe9b..9681f8d67ef8e44ce8682c020d579415d316ae94 100644
--- a/lib/include/hid/hid_device.h
+++ b/lib/include/hid/hid_device.h
@@ -72,6 +72,8 @@ public:
 	 *  optional:
 	 *       d    - HID descriptor for the device, it will be queried
 	 *              if it is not supplied
+	 *
+	 *  throws std::runtime_error() on error
 	 */
 	hid_device(util::shared_cap_chan kbd_chan, util::shared_cap_chan sdp_chan,
 			hid_watcher *parent, int cons_fd, bool uinput,
@@ -88,6 +90,8 @@ public:
 	 *
 	 * The device will not be functional until the interrupt channel
 	 * has been opened.
+	 *
+	 * throws std::runtime_error() on error
 	 */
 	void intr_opened(util::unique_fd &&intr_fd);
 
diff --git a/lib/include/l2cap_socket.h b/lib/include/l2cap_socket.h
index a8c33b4643707d51f0cf15ac6238c78a82994d2e..df59777841e6c5e322ae8f1fe6020eaf1e5f960e 100644
--- a/lib/include/l2cap_socket.h
+++ b/lib/include/l2cap_socket.h
@@ -83,6 +83,8 @@ public:
 	 *
 	 * chan is a handle for the blue.l2cap service acquired using
 	 * make_cap_chan() in util/shared_cap_chan.h.
+	 *
+	 * throws std::runtime_error() on error
 	 */
 	l2cap_listen_socket(util::shared_cap_chan chan, ev::loop_ref loop,
 	                    l2cap_listen_observer *parent, uint16_t psm);
diff --git a/lib/include/sdp_parser.h b/lib/include/sdp_parser.h
index 963238a44f432d59925875bf685c6ea9138ff1e5..448be026e60d4da5547c9f4c81d89c102c541d8c 100644
--- a/lib/include/sdp_parser.h
+++ b/lib/include/sdp_parser.h
@@ -92,6 +92,9 @@ class entry;
  * By creating an attr object from an sdp_attr, it is parsed into an
  * AST. Each node in the AST is represented by a class entry object,
  * from which specialised types are inherited.
+ *
+ * all operators can throw std::range_error() and std::runtime_error()
+ * if the SDP attribute being parsed is invalid
  */
 class attr
 {
diff --git a/lib/src/btdevice.cpp b/lib/src/btdevice.cpp
index ef6423ed52058a7eaefcf13882b01adc5e8f5e5f..dcaf43e07079ee7acfaa98ea9fc24f397a46bb30 100644
--- a/lib/src/btdevice.cpp
+++ b/lib/src/btdevice.cpp
@@ -104,7 +104,7 @@ const std::string &btdevice::get_pin() const
 void btdevice::set_pin(std::string new_pin)
 {
 	if (new_pin.size() > NG_HCI_PIN_SIZE)
-		throw std::length_error("PIN is too long");
+		throw std::runtime_error("PIN is too long");
 	pin = new_pin;
 }
 
@@ -448,7 +448,7 @@ void btdevice::process_state(device_event event)
 				   << NG_HCI_PIN_SIZE
 				   <<   ") for device " << addr
 				   << ". Code set to default 0000.";
-				throw std::length_error(ss.str());
+				throw std::runtime_error(ss.str());
 			}
 
 			std::copy(addr.cbegin(), addr.cend(), cp.bdaddr.b);
diff --git a/lib/src/hid/bthid.cpp b/lib/src/hid/bthid.cpp
index 58cf5c29b007f340c24d290669d94e951627a195..9456671d2684423dafd6e9a8e005bef81469a3ac 100644
--- a/lib/src/hid/bthid.cpp
+++ b/lib/src/hid/bthid.cpp
@@ -12,6 +12,7 @@
 
 #include "cap_sdp.h"
 #include "sdp_parser.h"
+#include "hid_post_process.h"
 
 
 #define SDP_SINGLE_ATTR(val) SDP_ATTR_RANGE((val), (val))
diff --git a/lib/src/hid/hid_post_process.h b/lib/src/hid/hid_post_process.h
new file mode 100644
index 0000000000000000000000000000000000000000..8e566886a23666346d845a04c6fcf2f6e05145b2
--- /dev/null
+++ b/lib/src/hid/hid_post_process.h
@@ -0,0 +1,13 @@
+#ifndef HID_POST_PROCESS_H
+#define HID_POST_PROCESS_H
+
+namespace blue::hid
+{
+
+/*
+ * Fill in fields in the hid descriptor from the raw USB descriptor.
+ */
+int32_t process_hid_descriptor(hid_descriptor &d);
+
+}; // namespace blue::hid
+#endif // HID_POST_PROCESS_H