diff --git a/src/sip/sip_utils.cpp b/src/sip/sip_utils.cpp
index 3558eebbbca9c970993e34d1d4fc00a9387416c9..52aba606624ff5e259ce650b805ca197accce2a3 100644
--- a/src/sip/sip_utils.cpp
+++ b/src/sip/sip_utils.cpp
@@ -44,6 +44,15 @@
 
 namespace ring { namespace sip_utils {
 
+std::string
+PjsipErrorCategory::message( int condition ) const
+{
+    std::string err_msg;
+    err_msg.reserve(PJ_ERR_MSG_SIZE);
+    err_msg.resize(pj_strerror(condition, &err_msg[0], err_msg.size()).slen);
+    return err_msg;
+}
+
 std::string
 fetchHeaderValue(pjsip_msg *msg, const std::string &field)
 {
diff --git a/src/sip/sip_utils.h b/src/sip/sip_utils.h
index 74ee3221ca7a99267e77ecf10ff8f9a56155cf4e..353b9d371339575a8d66a6b889cb4d37379d26cd 100644
--- a/src/sip/sip_utils.h
+++ b/src/sip/sip_utils.h
@@ -47,6 +47,29 @@ static constexpr int DEFAULT_SIP_TLS_PORT {5061};
 
 enum class KeyExchangeProtocol { NONE, SDES };
 
+/// PjsipErrorCategory - a PJSIP error category for std::error_code
+class PjsipErrorCategory final : public std::error_category
+{
+public:
+    const char* name() const noexcept override { return "pjsip"; }
+    std::string message( int condition ) const override;
+};
+
+/// PJSIP related exception
+/// Based on std::system_error with code() returning std::error_code with PjsipErrorCategory category
+class PjsipFailure : public std::system_error
+{
+private:
+    static constexpr const char* what_ = "PJSIP call failed";
+
+public:
+    PjsipFailure()
+        : std::system_error(std::error_code(PJ_EUNKNOWN, PjsipErrorCategory()), what_) {}
+
+    explicit PjsipFailure(pj_status_t status)
+        : std::system_error(std::error_code(status, PjsipErrorCategory()), what_) {}
+};
+
 static constexpr const char* getKeyExchangeName(KeyExchangeProtocol kx) {
     return kx == KeyExchangeProtocol::SDES ? "sdes" : "";
 }