You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@trafficserver.apache.org by dm...@apache.org on 2024/03/12 09:29:46 UTC

(trafficserver) branch master updated: libsowc - remove legacy Errata. (#10986)

This is an automated email from the ASF dual-hosted git repository.

dmeden pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/trafficserver.git


The following commit(s) were added to refs/heads/master by this push:
     new ab95203602 libsowc - remove legacy Errata. (#10986)
ab95203602 is described below

commit ab952036020bb2ba15a69caaec362719f209e16b
Author: Damian Meden <dm...@apache.org>
AuthorDate: Tue Mar 12 10:29:39 2024 +0100

    libsowc - remove legacy Errata. (#10986)
    
    libsowc - remove legacy Errata.
    
    ---------
    
    Co-authored-by: Alan M. Carroll <am...@apache.org>
---
 include/iocore/net/YamlSNIConfig.h                 |    5 +-
 include/mgmt/config/FileManager.h                  |   22 +-
 include/mgmt/rpc/handlers/common/ErrorUtils.h      |   22 +-
 include/mgmt/rpc/handlers/common/RecordsUtils.h    |    3 +-
 include/mgmt/rpc/handlers/config/Configuration.h   |    4 +-
 include/mgmt/rpc/handlers/plugins/Plugins.h        |    2 +-
 include/mgmt/rpc/handlers/records/Records.h        |   16 +-
 include/mgmt/rpc/handlers/server/Server.h          |    4 +-
 include/mgmt/rpc/handlers/storage/Storage.h        |    4 +-
 include/mgmt/rpc/jsonrpc/Context.h                 |    8 +-
 include/mgmt/rpc/jsonrpc/Defs.h                    |   11 +-
 include/mgmt/rpc/jsonrpc/JsonRPCManager.h          |    9 +-
 include/mgmt/rpc/jsonrpc/json/YAMLCodec.h          |   14 +-
 include/mgmt/rpc/server/CommBase.h                 |    2 +-
 include/mgmt/rpc/server/IPCSocketServer.h          |    4 +-
 include/tscore/Errata.h                            | 1047 --------------------
 include/tsutil/ts_errata.h                         |   82 +-
 lib/swoc/include/swoc/Errata.h                     |    1 +
 src/api/InkAPI.cc                                  |    4 +-
 src/iocore/net/SSLSNIConfig.cc                     |    4 +-
 src/iocore/net/YamlSNIConfig.cc                    |   14 +-
 src/iocore/net/unit_tests/test_YamlSNIConfig.cc    |   10 +-
 src/mgmt/config/AddConfigFilesHere.cc              |    1 -
 src/mgmt/config/FileManager.cc                     |   45 +-
 src/mgmt/rpc/CMakeLists.txt                        |   14 +-
 src/mgmt/rpc/handlers/common/ErrorUtils.cc         |   69 ++
 src/mgmt/rpc/handlers/config/Configuration.cc      |   22 +-
 src/mgmt/rpc/handlers/plugins/Plugins.cc           |    4 +-
 src/mgmt/rpc/handlers/records/Records.cc           |   10 +-
 src/mgmt/rpc/handlers/server/Server.cc             |   14 +-
 src/mgmt/rpc/handlers/storage/Storage.cc           |   16 +-
 src/mgmt/rpc/jsonrpc/Context.cc                    |    4 +-
 src/mgmt/rpc/jsonrpc/JsonRPCManager.cc             |   45 +-
 .../rpc/jsonrpc/unit_tests/test_basic_protocol.cc  |   46 +-
 src/mgmt/rpc/server/IPCSocketServer.cc             |   16 +-
 src/mgmt/rpc/server/unit_tests/test_rpcserver.cc   |    6 +-
 src/proxy/CMakeLists.txt                           |    2 +-
 src/proxy/HostStatus.cc                            |   18 +-
 src/proxy/http/HttpConfig.cc                       |    2 +
 src/traffic_cache_tool/CacheTool.cc                |    1 +
 src/tscore/CMakeLists.txt                          |    2 -
 src/tscore/Errata.cc                               |  269 -----
 src/tscore/unit_tests/test_Errata.cc               |   60 --
 src/tsutil/CMakeLists.txt                          |    2 +
 src/tsutil/ts_errata.cc                            |   34 +
 .../jsonrpc/plugins/jsonrpc_plugin_handler_test.cc |    2 +-
 46 files changed, 417 insertions(+), 1579 deletions(-)

diff --git a/include/iocore/net/YamlSNIConfig.h b/include/iocore/net/YamlSNIConfig.h
index 6ac8d76119..aa5ec2008d 100644
--- a/include/iocore/net/YamlSNIConfig.h
+++ b/include/iocore/net/YamlSNIConfig.h
@@ -32,8 +32,7 @@
 #include "iocore/net/SSLTypes.h"
 
 #include "tsutil/ts_ip.h"
-
-#include "tscore/Errata.h"
+#include "tsutil/ts_errata.h"
 
 #define TSDECL(id) constexpr char TS_##id[] = #id
 TSDECL(fqdn);
@@ -129,7 +128,7 @@ struct YamlSNIConfig {
     void populate_sni_actions(action_vector_t &actions);
   };
 
-  ts::Errata loader(const std::string &cfgFilename);
+  swoc::Errata loader(const std::string &cfgFilename);
 
   std::vector<YamlSNIConfig::Item> items;
 };
diff --git a/include/mgmt/config/FileManager.h b/include/mgmt/config/FileManager.h
index 60792e7142..28262acf51 100644
--- a/include/mgmt/config/FileManager.h
+++ b/include/mgmt/config/FileManager.h
@@ -23,19 +23,19 @@
 
 #pragma once
 
-#include "tscore/ink_mutex.h"
-#include "tscore/List.h"
-
-#include "tscore/Errata.h"
-
-#include "mgmt/rpc/jsonrpc/JsonRPC.h"
-
 #include <unordered_map>
 #include <string_view>
 #include <forward_list>
 #include <mutex>
 #include <functional>
 
+#include "tsutil/ts_errata.h"
+
+#include "tscore/ink_mutex.h"
+#include "tscore/List.h"
+
+#include <mgmt/rpc/jsonrpc/JsonRPC.h>
+
 class ConfigUpdateCbTable;
 
 class FileManager
@@ -121,7 +121,7 @@ public:
     time_t fileLastModified = 0;
   };
 
-  using CallbackType = std::function<ts::Errata(std::string const &, std::string const &)>;
+  using CallbackType = std::function<swoc::Errata(std::string const &, std::string const &)>;
 
   ~FileManager();
   FileManager(const FileManager &obj)         = delete;
@@ -139,8 +139,8 @@ public:
     _configCallbacks.push_front(std::move(f));
   }
 
-  ts::Errata fileChanged(std::string const &fileName, std::string const &configName);
-  ts::Errata rereadConfig();
+  swoc::Errata fileChanged(std::string const &fileName, std::string const &configName);
+  swoc::Errata rereadConfig();
   bool isConfigStale();
   void configFileChild(const char *parent, const char *child);
 
@@ -169,7 +169,7 @@ private:
   void addFileHelper(const char *fileName, const char *configName, bool root_access_needed, bool isRequired,
                      ConfigManager *parentConfig);
   /// JSONRPC endpoint
-  ts::Rv<YAML::Node> get_files_registry_rpc_endpoint(std::string_view const &id, YAML::Node const &params);
+  swoc::Rv<YAML::Node> get_files_registry_rpc_endpoint(std::string_view const &id, YAML::Node const &params);
 };
 
 void initializeRegistry(); // implemented in AddConfigFilesHere.cc
diff --git a/include/mgmt/rpc/handlers/common/ErrorUtils.h b/include/mgmt/rpc/handlers/common/ErrorUtils.h
index 1cf1f4b881..8d7d750c0a 100644
--- a/include/mgmt/rpc/handlers/common/ErrorUtils.h
+++ b/include/mgmt/rpc/handlers/common/ErrorUtils.h
@@ -26,7 +26,8 @@
 #include <system_error>
 #include <string_view>
 
-#include "tscore/Errata.h"
+#include "tsutil/ts_errata.h"
+#include "tsutil/ts_bw_format.h"
 
 namespace rpc::handlers::errors
 {
@@ -38,7 +39,7 @@ namespace rpc::handlers::errors
 // With this we try to avoid error codes collision. You can also use same error Code for all your
 // errors.
 enum Codes : unsigned int {
-  CONFIGURATION = 1,
+  CONFIGURATION = 999, // go past @c errno
   METRIC        = 1000,
   RECORD        = 2000,
   SERVER        = 3000,
@@ -48,19 +49,24 @@ enum Codes : unsigned int {
   GENERIC = 30000
 };
 
-static constexpr int ERRATA_DEFAULT_ID{1};
+std::error_code make_error_code(rpc::handlers::errors::Codes e);
 
 template <typename... Args>
-static inline ts::Errata
+static inline swoc::Errata
 make_errata(int code, std::string_view fmt, Args &&...args)
 {
-  std::string text;
-  return ts::Errata{}.push(ERRATA_DEFAULT_ID, code, swoc::bwprint(text, fmt, std::forward<Args>(args)...));
+  return swoc::Errata(std::error_code(code, std::generic_category()), fmt, std::forward<Args>(args)...);
 }
 
-static inline ts::Errata
+static inline swoc::Errata
 make_errata(int code, std::string_view text)
 {
-  return ts::Errata{}.push(ERRATA_DEFAULT_ID, code, text);
+  return swoc::Errata(std::error_code(code, std::generic_category()), std::string(text));
 }
 } // namespace rpc::handlers::errors
+namespace std
+{
+template <> struct is_error_code_enum<rpc::handlers::errors::Codes> : true_type {
+};
+
+} // namespace std
diff --git a/include/mgmt/rpc/handlers/common/RecordsUtils.h b/include/mgmt/rpc/handlers/common/RecordsUtils.h
index a8b047a614..22be1e9416 100644
--- a/include/mgmt/rpc/handlers/common/RecordsUtils.h
+++ b/include/mgmt/rpc/handlers/common/RecordsUtils.h
@@ -22,13 +22,14 @@
 
 #include <tuple>
 
+#include "tsutil/ts_errata.h"
+
 #include "mgmt/rpc/handlers/common/convert.h"
 #include "mgmt/rpc/handlers/common/ErrorUtils.h"
 
 #include "records/RecCore.h"
 #include "../../../../../src/records/P_RecCore.h"
 #include "tscore/Diags.h"
-#include "tscore/Errata.h"
 
 #include <yaml-cpp/yaml.h>
 
diff --git a/include/mgmt/rpc/handlers/config/Configuration.h b/include/mgmt/rpc/handlers/config/Configuration.h
index a79fc6d483..e6f00b5aea 100644
--- a/include/mgmt/rpc/handlers/config/Configuration.h
+++ b/include/mgmt/rpc/handlers/config/Configuration.h
@@ -24,7 +24,7 @@
 
 namespace rpc::handlers::config
 {
-ts::Rv<YAML::Node> set_config_records(std::string_view const &id, YAML::Node const &params);
-ts::Rv<YAML::Node> reload_config(std::string_view const &id, YAML::Node const &params);
+swoc::Rv<YAML::Node> set_config_records(std::string_view const &id, YAML::Node const &params);
+swoc::Rv<YAML::Node> reload_config(std::string_view const &id, YAML::Node const &params);
 
 } // namespace rpc::handlers::config
diff --git a/include/mgmt/rpc/handlers/plugins/Plugins.h b/include/mgmt/rpc/handlers/plugins/Plugins.h
index 4f9e079e8a..250b90d4e6 100644
--- a/include/mgmt/rpc/handlers/plugins/Plugins.h
+++ b/include/mgmt/rpc/handlers/plugins/Plugins.h
@@ -24,5 +24,5 @@
 
 namespace rpc::handlers::plugins
 {
-ts::Rv<YAML::Node> plugin_send_basic_msg(std::string_view const &id, YAML::Node const &params);
+swoc::Rv<YAML::Node> plugin_send_basic_msg(std::string_view const &id, YAML::Node const &params);
 } // namespace rpc::handlers::plugins
diff --git a/include/mgmt/rpc/handlers/records/Records.h b/include/mgmt/rpc/handlers/records/Records.h
index 40fd9696b4..a1d86cab7f 100644
--- a/include/mgmt/rpc/handlers/records/Records.h
+++ b/include/mgmt/rpc/handlers/records/Records.h
@@ -22,7 +22,7 @@
 
 #include <string_view>
 #include <yaml-cpp/yaml.h>
-#include "tscore/Errata.h"
+#include "tsutil/ts_errata.h"
 
 namespace rpc::handlers::records
 {
@@ -34,27 +34,27 @@ namespace rpc::handlers::records
 /// lead the search.
 /// @param id JSONRPC client's id.
 /// @param params lookup_records query structure.
-/// @return ts::Rv<YAML::Node> A node or an error. If ok, the node will hold the @c "recordList" sequence with the findings. In case
-/// of any missed search, ie: when paseed types didn't match the found record(s), the particular error will be added to the @c
+/// @return swoc::Rv<YAML::Node> A node or an error. If ok, the node will hold the @c "recordList" sequence with the findings. In
+/// case of any missed search, ie: when paseed types didn't match the found record(s), the particular error will be added to the @c
 /// "errorList" field.
 ///
-ts::Rv<YAML::Node> lookup_records(std::string_view const &id, YAML::Node const &params);
+swoc::Rv<YAML::Node> lookup_records(std::string_view const &id, YAML::Node const &params);
 
 ///
 /// @brief A RPC function handler that clear all the metrics.
 ///
 /// @param id JSONRPC client's id.
 /// @param params Nothing, this will be ignored.
-/// @return ts::Rv<YAML::Node> An empty YAML::Node or the proper Errata with the tracked error.
+/// @return swoc::Rv<YAML::Node> An empty YAML::Node or the proper Errata with the tracked error.
 ///
-ts::Rv<YAML::Node> clear_all_metrics_records(std::string_view const &id, YAML::Node const &);
+swoc::Rv<YAML::Node> clear_all_metrics_records(std::string_view const &id, YAML::Node const &);
 
 ///
 /// @brief A RPC  function  handler that clear a specific set of metrics.
 /// The @c "errorList" field will only be set if there is any error cleaning a specific metric.
 /// @param id JSONRPC client's id.
 /// @param params A list of records to update. @see RequestRecordElement
-/// @return ts::Rv<YAML::Node> A YAML::Node or the proper Errata with the tracked error.
+/// @return swoc::Rv<YAML::Node> A YAML::Node or the proper Errata with the tracked error.
 ///
-ts::Rv<YAML::Node> clear_metrics_records(std::string_view const &id, YAML::Node const &params);
+swoc::Rv<YAML::Node> clear_metrics_records(std::string_view const &id, YAML::Node const &params);
 } // namespace rpc::handlers::records
diff --git a/include/mgmt/rpc/handlers/server/Server.h b/include/mgmt/rpc/handlers/server/Server.h
index 6b6bd26bc5..b66b535ca1 100644
--- a/include/mgmt/rpc/handlers/server/Server.h
+++ b/include/mgmt/rpc/handlers/server/Server.h
@@ -24,7 +24,7 @@
 
 namespace rpc::handlers::server
 {
-ts::Rv<YAML::Node> server_start_drain(std::string_view const &id, YAML::Node const &params);
-ts::Rv<YAML::Node> server_stop_drain(std::string_view const &id, YAML::Node const &);
+swoc::Rv<YAML::Node> server_start_drain(std::string_view const &id, YAML::Node const &params);
+swoc::Rv<YAML::Node> server_stop_drain(std::string_view const &id, YAML::Node const &);
 void server_shutdown(YAML::Node const &);
 } // namespace rpc::handlers::server
diff --git a/include/mgmt/rpc/handlers/storage/Storage.h b/include/mgmt/rpc/handlers/storage/Storage.h
index 47738e565f..d07282b5a4 100644
--- a/include/mgmt/rpc/handlers/storage/Storage.h
+++ b/include/mgmt/rpc/handlers/storage/Storage.h
@@ -24,6 +24,6 @@
 
 namespace rpc::handlers::storage
 {
-ts::Rv<YAML::Node> set_storage_offline(std::string_view const &id, YAML::Node const &params);
-ts::Rv<YAML::Node> get_storage_status(std::string_view const &id, YAML::Node const &params);
+swoc::Rv<YAML::Node> set_storage_offline(std::string_view const &id, YAML::Node const &params);
+swoc::Rv<YAML::Node> get_storage_status(std::string_view const &id, YAML::Node const &params);
 } // namespace rpc::handlers::storage
diff --git a/include/mgmt/rpc/jsonrpc/Context.h b/include/mgmt/rpc/jsonrpc/Context.h
index 920d1fbd3c..54d6086fde 100644
--- a/include/mgmt/rpc/jsonrpc/Context.h
+++ b/include/mgmt/rpc/jsonrpc/Context.h
@@ -23,7 +23,7 @@
 #include <functional>
 #include <string_view>
 
-#include "tscore/Errata.h"
+#include "tsutil/ts_errata.h"
 #include "ts/apidefs.h"
 #include "mgmt/rpc/handlers/common/ErrorUtils.h"
 
@@ -40,15 +40,15 @@ constexpr bool NON_RESTRICTED_API{false};
 ///
 class Context
 {
-  using checker_cb = std::function<void(TSRPCHandlerOptions const &, ts::Errata &)>;
+  using checker_cb = std::function<void(TSRPCHandlerOptions const &, swoc::Errata &)>;
   /// @brief Internal class to hold the permission checker part.
   struct Auth {
     /// Checks for permissions. This function checks for every registered permission checker.
     ///
     /// @param options Registered handler options.
-    /// @return ts::Errata The errata will be filled by each of the registered checkers, if there was any issue validating the
+    /// @return swoc::Errata The errata will be filled by each of the registered checkers, if there was any issue validating the
     ///                    call, then the errata reflects that.
-    ts::Errata is_blocked(TSRPCHandlerOptions const &options) const;
+    swoc::Errata is_blocked(TSRPCHandlerOptions const &options) const;
 
     /// Add permission checkers.
     template <typename F>
diff --git a/include/mgmt/rpc/jsonrpc/Defs.h b/include/mgmt/rpc/jsonrpc/Defs.h
index 22bcf021f1..00cf2a3e0f 100644
--- a/include/mgmt/rpc/jsonrpc/Defs.h
+++ b/include/mgmt/rpc/jsonrpc/Defs.h
@@ -23,6 +23,8 @@
 #include <string>
 #include <optional>
 
+#include "tsutil/ts_errata.h"
+
 #include <yaml-cpp/yaml.h>
 
 #include "mgmt/rpc/jsonrpc/error/RPCError.h"
@@ -40,17 +42,16 @@ const std::string JSONRPC_VERSION{"2.0"};
 class RPCHandlerResponse
 {
 public:
-  YAML::Node result; //!< The response from the registered handler.
-  ts::Errata errata; //!< The  error response from the registered handler.
+  YAML::Node result;   //!< The response from the registered handler.
+  swoc::Errata errata; //!< The  error response from the registered handler.
 };
 
 struct RPCResponseInfo {
   RPCResponseInfo(std::string const &id_) : id{id_} {} // Convenient
   RPCResponseInfo() = default;
-
   struct Error {
-    std::error_code ec;
-    ts::Errata data;
+    std::error_code ec; // protocol error track.
+    swoc::Errata data;  // internal error detail.
   };
 
   std::string id; //!< incoming request id (only used for method calls, empty means it's a notification as requests with empty id
diff --git a/include/mgmt/rpc/jsonrpc/JsonRPCManager.h b/include/mgmt/rpc/jsonrpc/JsonRPCManager.h
index 56b2d71e80..9506493465 100644
--- a/include/mgmt/rpc/jsonrpc/JsonRPCManager.h
+++ b/include/mgmt/rpc/jsonrpc/JsonRPCManager.h
@@ -28,7 +28,6 @@
 #include <variant>
 #include <mutex>
 
-#include "tscore/Errata.h"
 #include "tscore/Diags.h"
 #include "ts/apidefs.h"
 
@@ -66,7 +65,7 @@ private:
 
 public:
   // Possible RPC method signatures.
-  using MethodHandlerSignature       = std::function<ts::Rv<YAML::Node>(std::string_view const &, const YAML::Node &)>;
+  using MethodHandlerSignature       = std::function<swoc::Rv<YAML::Node>(std::string_view const &, const YAML::Node &)>;
   using PluginMethodHandlerSignature = std::function<void(std::string_view const &, const YAML::Node &)>;
   using NotificationHandlerSignature = std::function<void(const YAML::Node &)>;
 
@@ -216,8 +215,8 @@ private:
     bool remove_handler(std::string_view name);
 
     // JSONRPC API - here for now.
-    ts::Rv<YAML::Node> show_registered_handlers(std::string_view const &, const YAML::Node &);
-    ts::Rv<YAML::Node> get_service_descriptor(std::string_view const &, const YAML::Node &);
+    swoc::Rv<YAML::Node> show_registered_handlers(std::string_view const &, const YAML::Node &);
+    swoc::Rv<YAML::Node> get_service_descriptor(std::string_view const &, const YAML::Node &);
 
     // Supported handler endpoint types.
     using Method       = FunctionWrapper<MethodHandlerSignature>;
@@ -248,7 +247,7 @@ private:
       explicit operator bool() const;
       bool operator!() const;
       /// Invoke the actual handler callback.
-      ts::Rv<YAML::Node> invoke(specs::RPCRequestInfo const &request) const;
+      swoc::Rv<YAML::Node> invoke(specs::RPCRequestInfo const &request) const;
       /// Check if the handler was registered as method.
       bool is_method() const;
 
diff --git a/include/mgmt/rpc/jsonrpc/json/YAMLCodec.h b/include/mgmt/rpc/jsonrpc/json/YAMLCodec.h
index a8b3d3972a..ce8eb5a7e4 100644
--- a/include/mgmt/rpc/jsonrpc/json/YAMLCodec.h
+++ b/include/mgmt/rpc/jsonrpc/json/YAMLCodec.h
@@ -115,7 +115,7 @@ class yamlcpp_json_decoder
       return {request, error::RPCErrorCode::PARSE_ERROR};
     }
     // TODO  We may want to extend the error handling and inform the user if there is  more than one invalid field in the request,
-    // so far we notify only the first one, we can use the data field to add more errors in it. ts::Errata
+    // so far we notify only the first one, we can use the data field to add more errors in it. swoc::Errata
     return {request, {/*ok*/}};
   }
 
@@ -182,19 +182,19 @@ class yamlcpp_json_encoder
   /// @param json   output parameter. YAML::Emitter.
   ///
   static void
-  encode_error(std::error_code error, ts::Errata const &errata, YAML::Emitter &json)
+  encode_error(std::error_code error, swoc::Errata const &errata, YAML::Emitter &json)
   {
     json << YAML::Key << "error";
     json << YAML::BeginMap;
     json << YAML::Key << "code" << YAML::Value << error.value();
     json << YAML::Key << "message" << YAML::Value << error.message();
-    if (!errata.isOK()) {
+    if (!errata.is_ok()) {
       json << YAML::Key << "data";
       json << YAML::BeginSeq;
       for (auto const &err : errata) {
         json << YAML::BeginMap;
-        json << YAML::Key << "code" << YAML::Value << err.getCode();
-        json << YAML::Key << "message" << YAML::Value << err.text();
+        json << YAML::Key << "code" << YAML::Value << errata.code().value();
+        json << YAML::Key << "message" << YAML::Value << std::string{err.text().data(), err.text().size()};
         json << YAML::EndMap;
       }
       json << YAML::EndSeq;
@@ -204,7 +204,7 @@ class yamlcpp_json_encoder
 
   /// Convenience functions to call encode_error.
   static void
-  encode_error(ts::Errata const &errata, YAML::Emitter &json)
+  encode_error(swoc::Errata const &errata, YAML::Emitter &json)
   {
     encode_error({error::RPCErrorCode::ExecutionError}, errata, json);
   }
@@ -229,7 +229,7 @@ class yamlcpp_json_encoder
     }
     // Registered handler error: They have set the error on the response from the registered handler. This uses ExecutionError as
     // top error.
-    else if (!resp.callResult.errata.isOK()) {
+    else if (!resp.callResult.errata.is_ok()) {
       encode_error(resp.callResult.errata, json);
     }
     // A valid response: The registered handler have set the proper result and no error was flagged.
diff --git a/include/mgmt/rpc/server/CommBase.h b/include/mgmt/rpc/server/CommBase.h
index 30767d82aa..23bbb36503 100644
--- a/include/mgmt/rpc/server/CommBase.h
+++ b/include/mgmt/rpc/server/CommBase.h
@@ -21,7 +21,7 @@
 
 #include <system_error>
 
-#include <tscore/Errata.h>
+#include <tsutil/ts_errata.h>
 
 #include "mgmt/rpc/config/JsonRPCConfig.h"
 
diff --git a/include/mgmt/rpc/server/IPCSocketServer.h b/include/mgmt/rpc/server/IPCSocketServer.h
index 7c3ccfba30..854e571dc9 100644
--- a/include/mgmt/rpc/server/IPCSocketServer.h
+++ b/include/mgmt/rpc/server/IPCSocketServer.h
@@ -29,6 +29,8 @@
 
 #include "swoc/MemSpan.h"
 #include "swoc/BufferWriter.h"
+#include "tsutil/ts_bw_format.h"
+#include "tsutil/ts_errata.h"
 #include "tscore/Layout.h"
 
 #include "mgmt/rpc/server/CommBase.h"
@@ -134,7 +136,7 @@ private:
   void bind(std::error_code &ec);
   void listen(std::error_code &ec);
   void close();
-  void late_check_peer_credentials(int peedFd, TSRPCHandlerOptions const &options, ts::Errata &errata) const;
+  void late_check_peer_credentials(int peedFd, TSRPCHandlerOptions const &options, swoc::Errata &errata) const;
 
   std::atomic_bool _running;
 
diff --git a/include/tscore/Errata.h b/include/tscore/Errata.h
deleted file mode 100644
index 3db677d429..0000000000
--- a/include/tscore/Errata.h
+++ /dev/null
@@ -1,1047 +0,0 @@
-/** @file
-    Stacking error message handling.
-
-    The problem addressed by this library is the ability to pass back
-    detailed error messages from failures. It is hard to get good
-    diagnostics because the specific failures and general context are
-    located in very different stack frames. This library allows local
-    functions to pass back local messages which can be easily
-    augmented as the error travels up the stack frame.
-
-    This could be done with exceptions but
-    - That is more effort to implementation
-    - Generally more expensive.
-
-    Each message on a stack contains text and a numeric identifier.
-    The identifier value zero is reserved for messages that are not
-    errors so that information can be passed back even in the success
-    case.
-
-    The implementation takes the position that success is fast and
-    failure is expensive. Therefore it is optimized for the success
-    path, imposing very little overhead. On the other hand, if an
-    error occurs and is handled, that is generally so expensive that
-    optimizations are pointless (although, of course, one should not
-    be gratuitiously expensive).
-
-    The library also provides the @c Rv ("return value") template to
-    make returning values and status easier. This template allows a
-    function to return a value and status pair with minimal changes.
-    The pair acts like the value type in most situations, while
-    providing access to the status.
-
-    Each instance of an erratum is a wrapper class that emulates value
-    semantics (copy on write). This means passing even large message
-    stacks is inexpensive, involving only a pointer copy and reference
-    counter increment and decrement. A success value is represented by
-    an internal @c NULL so it is even cheaper to copy.
-
-    To further ease use, the library has the ability to define @a
-    sinks.  A sink is a function that acts on an erratum when it
-    becomes unreferenced. The indended use is to send the messages to
-    an output log. This makes reporting errors to a log from even
-    deeply nested functions easy while preserving the ability of the
-    top level logic to control such logging.
-
-    @section license License
-
-    Licensed to the Apache Software Foundation (ASF) under one
-    or more contributor license agreements.  See the NOTICE file
-    distributed with this work for additional information
-    regarding copyright ownership.  The ASF licenses this file
-    to you under the Apache License, Version 2.0 (the
-    "License"); you may not use this file except in compliance
-    with the License.  You may obtain a copy of the License at
-
-    http://www.apache.org/licenses/LICENSE-2.0
-
-    Unless required by applicable law or agreed to in writing, software
-    distributed under the License is distributed on an "AS IS" BASIS,
-    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-    See the License for the specific language governing permissions and
-    limitations under the License.
- */
-
-#pragma once
-#include <memory>
-#include <string>
-#include <iosfwd>
-#include <sstream>
-#include <deque>
-#include <system_error>
-#include "tscore/NumericType.h"
-#include "tscore/IntrusivePtr.h"
-
-namespace ts
-{
-/** Class to hold a stack of error messages (the "errata").
-    This is a smart handle class, which wraps the actual data
-    and can therefore be treated a value type with cheap copy
-    semantics. Default construction is very cheap.
- */
-class Errata
-{
-protected:
-  /// Implementation class.
-  struct Data;
-  /// Handle for implementation class instance.
-  using ImpPtr = IntrusivePtr<Data>;
-
-public:
-  using self = Errata; /// Self reference type.
-
-  /// Message ID.
-  using Id = NumericType<unsigned int, struct MsgIdTag>;
-
-  /* Tag / level / code severity.
-     This is intended for clients to use to provide additional
-     classification of a message. A severity code, as for syslog,
-     is a common use.
-
-  */
-  using Code = NumericType<unsigned int, struct CodeTag>;
-  struct Message;
-
-  using Container = std::deque<Message>; ///< Storage type for messages.
-  // We iterate backwards to look like a stack.
-  //    using iterator = Container::reverse_iterator; ///< Message iteration.
-  /// Message const iteration.
-  //    using const_iterator = Container::const_reverse_iterator;
-  /// Reverse message iteration.
-  //    using reverse_iterator = Container::iterator;
-  /// Reverse constant message iteration.
-  //    using const_reverse_iterator = Container::const_iterator;
-
-  /// Default constructor - empty errata, very fast.
-  Errata();
-  /// Copy constructor, very fast.
-  Errata(self const &that ///< Object to copy
-  );
-  /// Construct from string.
-  /// Message Id and Code are default.
-  explicit Errata(std::string const &text ///< Finalized message text.
-  );
-  /// Construct with @a id and @a text.
-  /// Code is default.
-  Errata(Id id,                  ///< Message id.
-         std::string const &text ///< Message text.
-  );
-  /// Construct with @a id, @a code, and @a text.
-  Errata(Id id,                  ///< Message text.
-         Code code,              ///< Message code.
-         std::string const &text ///< Message text.
-  );
-  /** Construct from a message instance.
-      This is equivalent to default constructing an @c errata and then
-      invoking @c push with an argument of @a msg.
-  */
-  Errata(Message const &msg ///< Message to push
-  );
-
-  /// Constructor with @a id and @a std::error_code
-  Errata(std::error_code const &ec ///< Standard error code.
-  );
-  /// Move constructor.
-  Errata(self &&that);
-  /// Move constructor from @c Message.
-  Errata(Message &&msg);
-
-  /// destructor
-  ~Errata();
-
-  /// Self assignment.
-  /// @return A reference to this object.
-  self &operator=(const self &that ///< Source instance.
-  );
-
-  /// Move assignment.
-  self &operator=(self &&that);
-
-  /** Assign message.
-      All other messages are discarded.
-      @return A reference to this object.
-  */
-  self &operator=(Message const &msg ///< Source message.
-  );
-
-  /** Push @a text as a message.
-      The message is constructed from just the @a text.
-      It becomes the top message.
-      @return A reference to this object.
-  */
-  self &push(std::string const &text);
-  /** Push @a text as a message with message @a id.
-      The message is constructed from @a text and @a id.
-      It becomes the top message.
-      @return A reference to this object.
-  */
-  self &push(Id id, std::string const &text);
-  /** Push @a text as a message with message @a id and @a code.
-      The message is constructed from @a text and @a id.
-      It becomes the top message.
-      @return A reference to this object.
-  */
-  self &push(Id id, Code code, std::string const &text);
-  /** Push a message.
-      @a msg becomes the top message.
-      @return A reference to this object.
-  */
-  self &push(Message const &msg);
-  self &push(Message &&msg);
-
-  /** Push a constructed @c Message.
-      The @c Message is set to have the @a id and @a code. The other arguments are converted
-      to strings and concatenated to form the message text.
-      @return A reference to this object.
-  */
-  template <typename... Args> self &push(Id id, Code code, Args const &...args);
-
-  /** Push a nested status.
-      @a err becomes the top item.
-      @return A reference to this object.
-  */
-  self &push(self const &err);
-
-  /** Access top message.
-      @return If the errata is empty, a default constructed message
-      otherwise the most recent message.
-   */
-  Message const &top() const;
-
-  /** Move messages from @a that to @c this errata.
-      Messages from @a that are put on the top of the
-      stack in @c this and removed from @a that.
-  */
-  self &pull(self &that);
-
-  /// Remove last message.
-  void pop();
-
-  /// Remove all messages.
-  void clear();
-
-  /** Inhibit logging.
-      @note This only affects @c this as a top level @c errata.
-      It has no effect on this @c this being logged as a nested
-      @c errata.
-  */
-  self &doNotLog();
-
-  friend std::ostream &operator<<(std::ostream &, self const &);
-
-  /// Default glue value (a newline) for text rendering.
-  static std::string const DEFAULT_GLUE;
-
-  /** Test status.
-
-      Equivalent to @c success but more convenient for use in
-      control statements.
-
-      @return @c true if no messages or last message has a zero
-      message ID, @c false otherwise.
-   */
-  operator bool() const;
-
-  /** Test errata for no failure condition.
-
-      Equivalent to @c operator @c bool but easier to invoke.
-
-      @return @c true if no messages or last message has a zero
-      message ID, @c false otherwise.
-   */
-  bool isOK() const;
-
-  /// Number of messages in the errata.
-  size_t size() const;
-
-  /*  Forward declares.
-      We have to make our own iterators as the least bad option. The problem
-      is that we have recursive structures so declaration order is difficult.
-      We can't use the container iterators here because the element type is
-      not yet defined. If we define the element type here, it can't contain
-      an Errata and we have to do funky things to get around that. So we
-      have our own iterators, which are just shadowing sublclasses of the
-      container iterators.
-   */
-  class iterator;
-  class const_iterator;
-
-  /// Reference to top item on the stack.
-  iterator begin();
-  /// Reference to top item on the stack.
-  const_iterator begin() const;
-  //! Reference one past bottom item on the stack.
-  iterator end();
-  //! Reference one past bottom item on the stack.
-  const_iterator end() const;
-
-  // Logging support.
-
-  /** Base class for erratum sink.
-      When an errata is abandoned, this will be called on it to perform
-      any client specific logging. It is passed around by handle so that
-      it doesn't have to support copy semantics (and is not destructed
-      until application shutdown). Clients can subclass this class in order
-      to preserve arbitrary data for the sink or retain a handle to the
-      sink for runtime modifications.
-   */
-  class Sink : public IntrusivePtrCounter
-  {
-  public:
-    using self   = Sink;               ///< Self reference type.
-    using Handle = IntrusivePtr<self>; ///< Handle type.
-
-    /// Handle an abandoned errata.
-    virtual void operator()(Errata const &) const = 0;
-    /// Force virtual destructor.
-    virtual ~Sink() {}
-  };
-
-  //! Register a sink for discarded erratum.
-  static void registerSink(Sink::Handle const &s);
-
-  /// Register a function as a sink.
-  using SinkHandlerFunction = void (*)(Errata const &);
-
-  // Wrapper class to support registering functions as sinks.
-  struct SinkFunctionWrapper : public Sink {
-    /// Constructor.
-    SinkFunctionWrapper(SinkHandlerFunction f) : m_f(f) {}
-    /// Operator to invoke the function.
-    void
-    operator()(Errata const &e) const override
-    {
-      m_f(e);
-    }
-    SinkHandlerFunction m_f; ///< Client supplied handler.
-  };
-
-  /// Register a sink function for abandoned erratum.
-  static void
-  registerSink(SinkHandlerFunction f)
-  {
-    registerSink(Sink::Handle(new SinkFunctionWrapper(f)));
-  }
-
-  /** Simple formatted output.
-
-      Each message is written to a line. All lines are indented with
-      whitespace @a offset characters. Lines are indented an
-      additional @a indent. This value is increased by @a shift for
-      each level of nesting of an @c Errata. if @a lead is not @c
-      NULL the indentation is overwritten by @a lead if @a indent is
-      non-zero. It acts as a "continuation" marker for nested
-      @c Errata.
-
-   */
-  std::ostream &write(std::ostream &out, ///< Output stream.
-                      int offset,        ///< Lead white space for every line.
-                      int indent,        ///< Additional indentation per line for messages.
-                      int shift,         ///< Additional @a indent for nested @c Errata.
-                      char const *lead   ///< Leading text for nested @c Errata.
-  ) const;
-  /// Simple formatted output to fixed sized buffer.
-  /// @return Number of characters written to @a buffer.
-  size_t write(char *buffer,    ///< Output buffer.
-               size_t n,        ///< Buffer size.
-               int offset,      ///< Lead white space for every line.
-               int indent,      ///< Additional indentation per line for messages.
-               int shift,       ///< Additional @a indent for nested @c Errata.
-               char const *lead ///< Leading text for nested @c Errata.
-  ) const;
-
-protected:
-  /// Construct from implementation pointer.
-  /// Used internally by nested classes.
-  Errata(ImpPtr const &ptr);
-  /// Implementation instance.
-  ImpPtr m_data;
-
-  /// Return the implementation instance, allocating and unsharing as needed.
-  Data *pre_write();
-  /// Force and return an implementation instance.
-  /// Does not follow copy on write.
-  Data const *instance();
-
-  /// Used for returns when no data is present.
-  static Message const NIL_MESSAGE;
-
-  friend struct Data;
-  friend class Item;
-};
-
-extern std::ostream &operator<<(std::ostream &os, Errata const &stat);
-
-/// Storage for a single message.
-struct Errata::Message {
-  using self = Message; ///< Self reference type.
-
-  /// Default constructor.
-  /// The message has Id = 0, default code,  and empty text.
-  Message() = default;
-
-  /// Construct from text.
-  /// Id is zero and Code is default.
-  Message(std::string const &text ///< Finalized message text.
-  );
-
-  /// Construct with @a id and @a text.
-  /// Code is default.
-  Message(Id id,                  ///< ID of message in table.
-          std::string const &text ///< Final text for message.
-  );
-
-  /// Construct with @a id, @a code, and @a text.
-  Message(Id id,                  ///< Message Id.
-          Code code,              ///< Message Code.
-          std::string const &text ///< Final text for message.
-  );
-
-  /// Construct with an @a id, @a code, and a @a message.
-  /// The message contents are created by converting the variable arguments
-  /// to strings using the stream operator and concatenated in order.
-  template <typename... Args>
-  Message(Id id,     ///< Message Id.
-          Code code, ///< Message Code.
-          Args const &...text);
-
-  /// Reset to the message to default state.
-  self &clear();
-
-  /// Set the message Id.
-  self &set(Id id ///< New message Id.
-  );
-
-  /// Set the code.
-  self &set(Code code ///< New code for message.
-  );
-
-  /// Set the text.
-  self &set(std::string const &text ///< New message text.
-  );
-
-  /// Set the text.
-  self &set(char const *text ///< New message text.
-  );
-
-  /// Set the errata.
-  self &set(Errata const &err ///< Errata to store.
-  );
-
-  /// Get the text of the message.
-  std::string const &text() const;
-
-  /// Get the code.
-  Code getCode() const;
-  /// Get the nested status.
-  /// @return A status object, which is not @c NULL if there is a
-  /// nested status stored in this item.
-  Errata getErrata() const;
-
-  /** The default message code.
-
-      This value is used as the Code value for constructing and
-      clearing messages. It can be changed to control the value
-      used for empty messages.
-  */
-  static Code Default_Code;
-
-  /// Type for overriding success message test.
-  using SuccessTest = bool (*)(Message const &m);
-
-  /** Success message test.
-
-      When a message is tested for being "successful", this
-      function is called. It may be overridden by a client.
-      The initial value is @c DEFAULT_SUCCESS_TEST.
-
-      @note This is only called when there are Messages in the
-      Errata. An empty Errata (@c NULL or empty stack) is always
-      a success. Only the @c top Message is checked.
-
-      @return @c true if the message indicates success,
-      @c false otherwise.
-  */
-  static SuccessTest Success_Test;
-
-  /// Indicate success if the message code is zero.
-  /// @note Used as the default success test.
-  static bool isCodeZero(Message const &m);
-
-  static SuccessTest const DEFAULT_SUCCESS_TEST;
-
-  template <typename... Args> static std::string stringify(Args const &...items);
-
-  Id m_id     = 0;            ///< Message ID.
-  Code m_code = Default_Code; ///< Message code.
-  std::string m_text;         ///< Final text.
-  Errata m_errata;            ///< Nested errata.
-};
-
-/** This is the implementation class for Errata.
-
-    It holds the actual messages and is treated as a passive data
-    object with nice constructors.
-
-    We implement reference counting semantics by hand for two
-    reasons. One is that we need to do some specialized things, but
-    mainly because the client can't see this class so we can't
-*/
-struct Errata::Data : public IntrusivePtrCounter {
-  using self = Data; ///< Self reference type.
-
-  //! Default constructor.
-  Data();
-
-  /// Destructor, to do logging.
-  ~Data();
-
-  //! Number of messages.
-  size_t size() const;
-
-  /// Get the top message on the stack.
-  Message const &top() const;
-
-  /// Put a message on top of the stack.
-  void push(Message const &msg);
-  void push(Message &&msg);
-
-  /// Log this when it is deleted.
-  mutable bool m_log_on_delete = true;
-
-  //! The message stack.
-  Container m_items;
-};
-
-/// Forward iterator for @c Messages in an @c Errata.
-class Errata::iterator : public Errata::Container::reverse_iterator
-{
-public:
-  using self  = iterator;                            ///< Self reference type.
-  using super = Errata::Container::reverse_iterator; ///< Parent type.
-  iterator();                                        ///< Default constructor.
-  /// Copy constructor.
-  iterator(self const &that ///< Source instance.
-  );
-  /// Construct from super class.
-  iterator(super const &that ///< Source instance.
-  );
-  /// Assignment.
-  self &operator=(self const &that);
-  /// Assignment from super class.
-  self &operator=(super const &that);
-  /// Prefix increment.
-  self &operator++();
-  /// Prefix decrement.
-  self &operator--();
-};
-
-/// Forward constant iterator for @c Messages in an @c Errata.
-class Errata::const_iterator : public Errata::Container::const_reverse_iterator
-{
-public:
-  using self  = const_iterator;                            ///< Self reference type.
-  using super = Errata::Container::const_reverse_iterator; ///< Parent type.
-  const_iterator();                                        ///< Default constructor.
-  /// Copy constructor.
-  const_iterator(self const &that ///< Source instance.
-  );
-  const_iterator(super const &that ///< Source instance.
-  );
-  /// Assignment.
-  self &operator=(self const &that);
-  /// Assignment from super class.
-  self &operator=(super const &that);
-  /// Prefix increment.
-  self &operator++();
-  /// Prefix decrement.
-  self &operator--();
-};
-
-/** Helper class for @c Rv.
-    This class enables us to move the implementation of non-templated methods
-    and members out of the header file for a cleaner API.
- */
-struct RvBase {
-  Errata _errata; ///< The status from the function.
-
-  /** Default constructor. */
-  RvBase();
-
-  /** Construct with specific status.
-   */
-  RvBase(Errata const &s ///< Status to copy
-  );
-
-  /** Construct with specific status.
-   */
-  RvBase(Errata &&s ///< Status to move
-  );
-
-  //! Test the return value for success.
-  bool isOK() const;
-
-  /** Clear any stacked errors.
-      This is useful during shutdown, to silence irrelevant errors caused
-      by the shutdown process.
-  */
-  void clear();
-
-  /// Inhibit logging of the errata.
-  void doNotLog();
-};
-
-/** Return type for returning a value and status (errata).  In
-    general, a method wants to return both a result and a status so
-    that errors are logged properly. This structure is used to do that
-    in way that is more usable than just @c std::pair.  - Simpler and
-    shorter typography - Force use of @c errata rather than having to
-    remember it (and the order) each time - Enable assignment directly
-    to @a R for ease of use and compatibility so clients can upgrade
-    asynchronously.
- */
-template <typename R> struct Rv : public RvBase {
-  using self   = Rv;     ///< Standard self reference type.
-  using super  = RvBase; ///< Standard super class reference type.
-  using Result = R;      ///< Type of result value.
-
-  Result _result; ///< The actual result of the function.
-
-  /** Default constructor.
-      The default constructor for @a R is used.
-      The status is initialized to SUCCESS.
-  */
-  Rv();
-
-  /** Standard (success) constructor.
-
-      This copies the result and sets the status to SUCCESS.
-
-      @note Not @c explicit so that clients can return just a result
-       and have it be marked as SUCCESS.
-   */
-  Rv(Result const &r ///< The function result
-  );
-
-  /** Construct from a result and a pre-existing status object.
-
-      @internal No constructor from just an Errata to avoid
-      potential ambiguity with constructing from result type.
-   */
-  Rv(Result const &r, ///< The function result
-     Errata const &s  ///< A pre-existing status object
-  );
-
-  Rv(Errata &&errata);
-  /** User conversion to the result type.
-
-      This makes it easy to use the function normally or to pass the
-      result only to other functions without having to extract it by
-      hand.
-  */
-  operator Result const &() const;
-
-  /** Assignment from result type.
-
-      This allows the result to be assigned to a pre-declared return
-      value structure.  The return value is a reference to the
-      internal result so that this operator can be chained in other
-      assignments to instances of result type. This is most commonly
-      used when the result is computed in to a local variable to be
-      both returned and stored in a member.
-
-      @code
-      Rv<int> zret;
-      int value;
-      // ... complex computations, result in value
-      this->m_value = zret = value;
-      // ...
-      return zret;
-      @endcode
-
-      @return A reference to the copy of @a r stored in this object.
-  */
-  Result &
-  operator=(Result const &r ///< Result to assign
-  )
-  {
-    _result = r;
-    return _result;
-  }
-
-  /** Add the status from another instance to this one.
-      @return A reference to @c this object.
-  */
-  template <typename U>
-  self &push(Rv<U> const &that ///< Source of status messages
-  );
-
-  /** Set the result.
-
-      This differs from assignment of the function result in that the
-      return value is a reference to the @c Rv, not the internal
-      result. This makes it useful for assigning a result local
-      variable and then returning.
-
-      @code
-      Rv<int> zret;
-      int value;
-      // ... complex computation, result in value
-      return zret.set(value);
-      @endcode
-  */
-  self &set(Result const &r ///< Result to store
-  );
-
-  /** Return the result.
-      @return A reference to the result value in this object.
-  */
-  Result &result();
-
-  /** Return the result.
-      @return A reference to the result value in this object.
-  */
-  Result const &result() const;
-
-  /** Return the status.
-      @return A reference to the @c errata in this object.
-  */
-  Errata &errata();
-
-  /** Return the status.
-      @return A reference to the @c errata in this object.
-  */
-  Errata const &errata() const;
-
-  /// Directly set the errata
-  self &operator=(Errata const &status ///< Errata to assign.
-  );
-
-  /// Push a message on to the status.
-  self &push(Errata::Message const &msg);
-};
-
-/** Combine a function result and status in to an @c Rv.
-    This is useful for clients that want to declare the status object
-    and result independently.
- */
-template <typename R>
-Rv<R>
-MakeRv(R const &r,     ///< The function result
-       Errata const &s ///< The pre-existing status object
-)
-{
-  return Rv<R>(r, s);
-}
-/* ----------------------------------------------------------------------- */
-/* ----------------------------------------------------------------------- */
-// Inline methods.
-inline Errata::Message::Message(std::string const &text) : m_text(text) {}
-inline Errata::Message::Message(Id id, std::string const &text) : m_id(id), m_text(text) {}
-inline Errata::Message::Message(Id id, Code code, std::string const &text) : m_id(id), m_code(code), m_text(text) {}
-template <typename... Args>
-Errata::Message::Message(Id id, Code code, Args const &...text) : m_id(id), m_code(code), m_text(stringify(text...))
-{
-}
-
-inline Errata::Message &
-Errata::Message::clear()
-{
-  m_id   = 0;
-  m_code = Default_Code;
-  m_text.erase();
-  m_errata.clear();
-  return *this;
-}
-
-inline std::string const &
-Errata::Message::text() const
-{
-  return m_text;
-}
-inline Errata::Code
-Errata::Message::getCode() const
-{
-  return m_code;
-}
-inline Errata
-Errata::Message::getErrata() const
-{
-  return m_errata;
-}
-
-inline Errata::Message &
-Errata::Message::set(Id id)
-{
-  m_id = id;
-  return *this;
-}
-inline Errata::Message &
-Errata::Message::set(Code code)
-{
-  m_code = code;
-  return *this;
-}
-inline Errata::Message &
-Errata::Message::set(std::string const &text)
-{
-  m_text = text;
-  return *this;
-}
-inline Errata::Message &
-Errata::Message::set(char const *text)
-{
-  m_text = text;
-  return *this;
-}
-inline Errata::Message &
-Errata::Message::set(Errata const &err)
-{
-  m_errata = err;
-  m_errata.doNotLog();
-  return *this;
-}
-
-template <typename... Args>
-std::string
-Errata::Message::stringify(Args const &...items)
-{
-  std::ostringstream s;
-  (void)(int[]){0, ((s << items), 0)...};
-  return s.str();
-}
-
-inline Errata::Errata() {}
-inline Errata::Errata(Id id, Code code, std::string const &text)
-{
-  this->push(Message(id, code, text));
-}
-inline Errata::Errata(Message const &msg)
-{
-  this->push(msg);
-}
-inline Errata::Errata(Message &&msg)
-{
-  this->push(std::move(msg));
-}
-inline Errata::Errata(std::error_code const &ec)
-{
-  auto cond = ec.category().default_error_condition(ec.value());
-  this->push(cond.value(), // we use the classification from the error_condition.
-             ec.value(), ec.message());
-}
-
-inline Errata::operator bool() const
-{
-  return this->isOK();
-}
-
-inline size_t
-Errata::size() const
-{
-  return m_data ? m_data->m_items.size() : 0;
-}
-
-inline bool
-Errata::isOK() const
-{
-  return nullptr == m_data || 0 == m_data->size() || Message::Success_Test(this->top());
-}
-
-inline Errata &
-Errata::push(std::string const &text)
-{
-  this->push(Message(text));
-  return *this;
-}
-
-inline Errata &
-Errata::push(Id id, std::string const &text)
-{
-  this->push(Message(id, text));
-  return *this;
-}
-
-inline Errata &
-Errata::push(Id id, Code code, std::string const &text)
-{
-  this->push(Message(id, code, text));
-  return *this;
-}
-
-template <typename... Args>
-auto
-Errata::push(Id id, Code code, Args const &...args) -> self &
-{
-  this->push(Message(id, code, args...));
-  return *this;
-}
-
-inline Errata &
-Errata::push(Errata const &err)
-{
-  for (auto const &e : err) {
-    this->push(e.m_id, e.m_code, e.m_text);
-    // e.m_errata??
-  }
-  return *this;
-}
-
-inline Errata::Message const &
-Errata::top() const
-{
-  return m_data ? m_data->top() : NIL_MESSAGE;
-}
-inline Errata &
-Errata::doNotLog()
-{
-  this->instance()->m_log_on_delete = false;
-  return *this;
-}
-
-inline Errata::Data::Data() {}
-inline size_t
-Errata::Data::size() const
-{
-  return m_items.size();
-}
-
-inline Errata::iterator::iterator() {}
-inline Errata::iterator::iterator(self const &that) : super(that) {}
-inline Errata::iterator::iterator(super const &that) : super(that) {}
-inline Errata::iterator &
-Errata::iterator::operator=(self const &that)
-{
-  this->super::operator=(that);
-  return *this;
-}
-inline Errata::iterator &
-Errata::iterator::operator=(super const &that)
-{
-  this->super::operator=(that);
-  return *this;
-}
-inline Errata::iterator &
-Errata::iterator::operator++()
-{
-  this->super::operator++();
-  return *this;
-}
-inline Errata::iterator &
-Errata::iterator::operator--()
-{
-  this->super::operator--();
-  return *this;
-}
-
-inline Errata::const_iterator::const_iterator() {}
-inline Errata::const_iterator::const_iterator(self const &that) : super(that) {}
-inline Errata::const_iterator::const_iterator(super const &that) : super(that) {}
-inline Errata::const_iterator &
-Errata::const_iterator::operator=(self const &that)
-{
-  super::operator=(that);
-  return *this;
-}
-inline Errata::const_iterator &
-Errata::const_iterator::operator=(super const &that)
-{
-  super::operator=(that);
-  return *this;
-}
-inline Errata::const_iterator &
-Errata::const_iterator::operator++()
-{
-  this->super::operator++();
-  return *this;
-}
-inline Errata::const_iterator &
-Errata::const_iterator::operator--()
-{
-  this->super::operator--();
-  return *this;
-}
-
-inline RvBase::RvBase() {}
-inline RvBase::RvBase(Errata const &errata) : _errata(errata) {}
-inline RvBase::RvBase(Errata &&errata) : _errata(std::move(errata)) {}
-inline bool
-RvBase::isOK() const
-{
-  return _errata;
-}
-inline void
-RvBase::clear()
-{
-  _errata.clear();
-}
-inline void
-RvBase::doNotLog()
-{
-  _errata.doNotLog();
-}
-
-template <typename T> Rv<T>::Rv() : _result() {}
-template <typename T> Rv<T>::Rv(Result const &r) : _result(r) {}
-template <typename T> Rv<T>::Rv(Result const &r, Errata const &errata) : super(errata), _result(r) {}
-template <typename T> Rv<T>::Rv(Errata &&errata) : super(std::move(errata)) {}
-template <typename T> Rv<T>::operator Result const &() const
-{
-  return _result;
-}
-template <typename T>
-T const &
-Rv<T>::result() const
-{
-  return _result;
-}
-template <typename T>
-T &
-Rv<T>::result()
-{
-  return _result;
-}
-template <typename T>
-Errata const &
-Rv<T>::errata() const
-{
-  return _errata;
-}
-template <typename T>
-Errata &
-Rv<T>::errata()
-{
-  return _errata;
-}
-template <typename T>
-Rv<T> &
-Rv<T>::set(Result const &r)
-{
-  _result = r;
-  return *this;
-}
-template <typename T>
-Rv<T> &
-Rv<T>::operator=(Errata const &errata)
-{
-  _errata = errata;
-  return *this;
-}
-template <typename T>
-Rv<T> &
-Rv<T>::push(Errata::Message const &msg)
-{
-  _errata.push(msg);
-  return *this;
-}
-template <typename T>
-template <typename U>
-Rv<T> &
-Rv<T>::push(Rv<U> const &that)
-{
-  _errata.push(that.errata());
-  return *this;
-}
-/* ----------------------------------------------------------------------- */
-/* ----------------------------------------------------------------------- */
-} // namespace ts
diff --git a/include/tsutil/ts_errata.h b/include/tsutil/ts_errata.h
index 427983bbbb..313d5ab54d 100644
--- a/include/tsutil/ts_errata.h
+++ b/include/tsutil/ts_errata.h
@@ -22,6 +22,7 @@ limitations under the License.
 #pragma once
 
 #include <utility>
+#include <unordered_map>
 
 #include "tsutil/ts_diag_levels.h"
 #include "swoc/TextView.h"
@@ -44,27 +45,20 @@ diags_level_of(swoc::Errata::Severity s)
   return static_cast<DiagsLevel>(static_cast<int>(s));
 }
 
-inline std::error_code
-ec_for()
-{
-  return std::error_code(errno, std::system_category());
-}
-inline std::error_code
-ec_for(int e)
-{
-  return std::error_code(e, std::system_category());
-}
-
 // This is treated as an array so must numerically match with @c DiagsLevel
 static constexpr std::array<swoc::TextView, 9> Severity_Names{
   {"Diag", "Debug", "Status", "Note", "Warn", "Error", "Fatal", "Alert", "Emergency"}
 };
 
+namespace ts
+{
+
 inline std::error_code
 make_errno_code()
 {
   return {errno, std::system_category()};
 }
+
 inline std::error_code
 make_errno_code(int err)
 {
@@ -77,3 +71,69 @@ bw_log(DiagsLevel lvl, swoc::TextView fmt, Args &&...args)
 {
   swoc::bwprint_v(ts::bw_dbg, fmt, std::forward_as_tuple(args...));
 }
+
+class err_category : public std::error_category
+{
+  using self_type = err_category;
+
+public:
+  /// @return Name of the category.
+  char const *name() const noexcept override;
+
+  /** Convert code to condition.
+   *
+   * @param code Numeric error code.
+   * @return The correspodning condition.
+   */
+  std::error_condition default_error_condition(int code) const noexcept override;
+
+  /** Is numeric error code equivalent to condition.
+   *
+   * @param code Numeric error code.
+   * @param condition Condition object.
+   * @return @a true if the arguments are equivalent.
+   */
+  bool equivalent(int code, std::error_condition const &condition) const noexcept override;
+
+  /** Is error code enumeration value equivalent to error code object.
+   *
+   * @param ec Condition object.
+   * @param code Numeric error code.
+   * @return @a true if the arguments are equivalent.
+   */
+  bool equivalent(std::error_code const &ec, int code) const noexcept override;
+
+  /// @return Text for @c code.
+  std::string message(int code) const override;
+
+protected:
+  using table_type = std::unordered_map<int, std::string>;
+  /// Mapping from numeric error code to message string.
+  static table_type const _table;
+};
+
+inline char const *
+ts::err_category::name() const noexcept
+{
+  return "trafficserver";
+}
+
+inline std::error_condition
+err_category::default_error_condition(int code) const noexcept
+{
+  return {code, *this};
+}
+
+inline bool
+err_category::equivalent(const std::error_code &ec, int code) const noexcept
+{
+  return ec.value() == code;
+}
+
+inline bool
+err_category::equivalent(int code, const std::error_condition &condition) const noexcept
+{
+  return code == condition.value();
+}
+
+} // namespace ts
diff --git a/lib/swoc/include/swoc/Errata.h b/lib/swoc/include/swoc/Errata.h
index 6ee0be5c25..fff9e17db1 100644
--- a/lib/swoc/include/swoc/Errata.h
+++ b/lib/swoc/include/swoc/Errata.h
@@ -1544,4 +1544,5 @@ get(swoc::Rv<R> const &rv) {
   throw std::domain_error("Errata index value out of bounds");
 }
 /// @endcond
+
 }} // namespace swoc::SWOC_VERSION_NS
diff --git a/src/api/InkAPI.cc b/src/api/InkAPI.cc
index 91cba8252f..a69938cfd6 100644
--- a/src/api/InkAPI.cc
+++ b/src/api/InkAPI.cc
@@ -117,7 +117,7 @@ namespace rpc
 {
 extern std::mutex g_rpcHandlingMutex;
 extern std::condition_variable g_rpcHandlingCompletion;
-extern ts::Rv<YAML::Node> g_rpcHandlerResponseData;
+extern swoc::Rv<YAML::Node> g_rpcHandlerResponseData;
 extern bool g_rpcHandlerProcessingCompleted;
 } // namespace rpc
 
@@ -8853,7 +8853,7 @@ TSRPCHandlerError(int ec, const char *descr, size_t descr_len)
 {
   Debug("rpc.api", ">> Handler seems to be done with an error");
   std::lock_guard<std::mutex> lock(rpc::g_rpcHandlingMutex);
-  ::rpc::g_rpcHandlerResponseData        = ts::Errata{}.push(1, ec, std::string{descr, descr_len});
+  ::rpc::g_rpcHandlerResponseData        = swoc::Errata(ts::make_errno_code(ec), "{}", swoc::TextView{descr, descr_len});
   ::rpc::g_rpcHandlerProcessingCompleted = true;
   ::rpc::g_rpcHandlingCompletion.notify_one();
   Debug("rpc.api", ">> error  flagged.");
diff --git a/src/iocore/net/SSLSNIConfig.cc b/src/iocore/net/SSLSNIConfig.cc
index 357abd9f16..5a0cd99e93 100644
--- a/src/iocore/net/SSLSNIConfig.cc
+++ b/src/iocore/net/SSLSNIConfig.cc
@@ -306,8 +306,8 @@ SNIConfigParams::initialize(std::string const &sni_filename)
   }
 
   YamlSNIConfig yaml_sni_tmp;
-  ts::Errata zret = yaml_sni_tmp.loader(sni_filename);
-  if (!zret.isOK()) {
+  auto zret = yaml_sni_tmp.loader(sni_filename);
+  if (!zret.is_ok()) {
     std::stringstream errMsg;
     errMsg << zret;
     if (TSSystemState::is_initializing()) {
diff --git a/src/iocore/net/YamlSNIConfig.cc b/src/iocore/net/YamlSNIConfig.cc
index e7c6919453..26d12b6e3a 100644
--- a/src/iocore/net/YamlSNIConfig.cc
+++ b/src/iocore/net/YamlSNIConfig.cc
@@ -38,6 +38,7 @@
 #include "swoc/TextView.h"
 #include "swoc/bwf_base.h"
 
+#include "iocore/net/YamlSNIConfig.h"
 #include "SNIActionPerformer.h"
 #include "P_SSLConfig.h"
 #include "P_SSLNetVConnection.h"
@@ -47,7 +48,6 @@
 #include "swoc/bwf_fwd.h"
 #include "tscore/Diags.h"
 #include "tscore/EnumDescriptor.h"
-#include "tscore/Errata.h"
 #include "tscore/ink_assert.h"
 
 #include "records/RecCore.h"
@@ -76,32 +76,32 @@ load_tunnel_alpn(std::vector<int> &dst, const YAML::Node &node)
 
 } // namespace
 
-ts::Errata
+swoc::Errata
 YamlSNIConfig::loader(const std::string &cfgFilename)
 {
   try {
     YAML::Node config = YAML::LoadFile(cfgFilename);
     if (config.IsNull()) {
-      return ts::Errata();
+      return {};
     }
 
     if (!config["sni"]) {
-      return ts::Errata::Message(1, 1, "expected a toplevel 'sni' node");
+      return swoc::Errata("expected a toplevel 'sni' node");
     }
 
     config = config["sni"];
     if (!config.IsSequence()) {
-      return ts::Errata::Message(1, 1, "expected sequence");
+      return swoc::Errata("expected sequence");
     }
 
     for (auto it = config.begin(); it != config.end(); ++it) {
       items.push_back(it->as<YamlSNIConfig::Item>());
     }
   } catch (std::exception &ex) {
-    return ts::Errata::Message(1, 1, ex.what());
+    return swoc::Errata("exception - {}", ex.what());
   }
 
-  return ts::Errata();
+  return swoc::Errata();
 }
 
 void
diff --git a/src/iocore/net/unit_tests/test_YamlSNIConfig.cc b/src/iocore/net/unit_tests/test_YamlSNIConfig.cc
index 58932567d2..9c809d9840 100644
--- a/src/iocore/net/unit_tests/test_YamlSNIConfig.cc
+++ b/src/iocore/net/unit_tests/test_YamlSNIConfig.cc
@@ -48,13 +48,13 @@ check_port_range(const YamlSNIConfig::Item &item, in_port_t min_expected, in_por
 TEST_CASE("YamlSNIConfig sets port ranges appropriately")
 {
   YamlSNIConfig conf{};
-  ts::Errata zret{conf.loader(_XSTR(LIBINKNET_UNIT_TEST_DIR) "/sni_conf_test.yaml")};
-  if (!zret.isOK()) {
+  swoc::Errata zret{conf.loader(_XSTR(LIBINKNET_UNIT_TEST_DIR) "/sni_conf_test.yaml")};
+  if (!zret.is_ok()) {
     std::stringstream errorstream;
     errorstream << zret;
     FAIL(errorstream.str());
   }
-  REQUIRE(zret.isOK());
+  REQUIRE(zret.is_ok());
   REQUIRE(conf.items.size() == 7);
 
   SECTION("If no ports were specified, port range should contain all ports.")
@@ -113,11 +113,11 @@ TEST_CASE("YamlConfig handles bad ports appropriately.")
   std::string filepath;
   swoc::bwprint(filepath, "{}/sni_conf_test_bad_port_{}.yaml", _XSTR(LIBINKNET_UNIT_TEST_DIR), port_str);
 
-  ts::Errata zret{conf.loader(filepath)};
+  swoc::Errata zret{conf.loader(filepath)};
   std::stringstream errorstream;
   errorstream << zret;
 
   std::string expected;
-  swoc::bwprint(expected, "1 [1]: yaml-cpp: error at line 20, column 5: bad port range: {}\n", port_str);
+  swoc::bwprint(expected, "Error: exception - yaml-cpp: error at line 20, column 5: bad port range: {}\n", port_str);
   CHECK(errorstream.str() == expected);
 }
diff --git a/src/mgmt/config/AddConfigFilesHere.cc b/src/mgmt/config/AddConfigFilesHere.cc
index 9e3fa3ef2d..e589a1bd90 100644
--- a/src/mgmt/config/AddConfigFilesHere.cc
+++ b/src/mgmt/config/AddConfigFilesHere.cc
@@ -26,7 +26,6 @@
 #include "../../records/P_RecCore.h"
 #include "tscore/Diags.h"
 #include "mgmt/config/FileManager.h"
-#include "tscore/Errata.h"
 
 static constexpr bool REQUIRED{true};
 static constexpr bool NOT_REQUIRED{false};
diff --git a/src/mgmt/config/FileManager.cc b/src/mgmt/config/FileManager.cc
index 3df746258c..8d9644b06e 100644
--- a/src/mgmt/config/FileManager.cc
+++ b/src/mgmt/config/FileManager.cc
@@ -45,18 +45,17 @@
 static constexpr auto logTag{"filemanager"};
 namespace
 {
-ts::Errata
+swoc::Errata
 handle_file_reload(std::string const &fileName, std::string const &configName)
 {
   Debug(logTag, "handling reload %s - %s", fileName.c_str(), configName.c_str());
-  ts::Errata ret;
+  swoc::Errata ret;
   // TODO: make sure records holds the name after change, if not we should change it.
   if (fileName == ts::filename::RECORDS) {
     if (auto zret = RecReadYamlConfigFile(); zret) {
       RecConfigWarnIfUnregistered();
     } else {
-      std::string str;
-      ret.push(1, swoc::bwprint(str, "Error reading {}. {}", fileName));
+      ret.note("Error reading {}", fileName).note(zret);
     }
   } else {
     RecT rec_type;
@@ -64,8 +63,7 @@ handle_file_reload(std::string const &fileName, std::string const &configName)
     if (RecGetRecordType(data, &rec_type) == REC_ERR_OKAY && rec_type == RECT_CONFIG) {
       RecSetSyncRequired(data);
     } else {
-      std::string str;
-      ret.push(1, swoc::bwprint(str, "Unknown file change {}.", configName));
+      ret.note("Unknown file change {}.", configName);
     }
   }
 
@@ -90,7 +88,7 @@ FileManager::FileManager()
 
   // Register the files registry jsonrpc endpoint
   rpc::add_method_handler("filemanager.get_files_registry",
-                          [this](std::string_view const &id, const YAML::Node &req) -> ts::Rv<YAML::Node> {
+                          [this](std::string_view const &id, const YAML::Node &req) -> swoc::Rv<YAML::Node> {
                             return get_files_registry_rpc_endpoint(id, req);
                           },
                           &rpc::core_ats_rpc_service_provider_handle, {{rpc::NON_RESTRICTED_API}});
@@ -163,17 +161,20 @@ FileManager::getConfigObj(const char *fileName, ConfigManager **rbPtr)
   return found;
 }
 
-ts::Errata
+swoc::Errata
 FileManager::fileChanged(std::string const &fileName, std::string const &configName)
 {
   Debug("filemanager", "file changed %s", fileName.c_str());
-  ts::Errata ret;
+  swoc::Errata ret;
 
   std::lock_guard<std::mutex> guard(_callbacksMutex);
   for (auto const &call : _configCallbacks) {
     if (auto const &r = call(fileName, configName); !r) {
       Debug("filemanager", "something back from callback %s", fileName.c_str());
-      std::for_each(r.begin(), r.end(), [&ret](auto &&e) { ret.push(e); });
+      if (ret.empty()) {
+        ret.note("Errors while reloading configurations.");
+      }
+      ret.note(r);
     }
   }
 
@@ -206,10 +207,10 @@ FileManager::invokeConfigPluginCallbacks()
 //   although it is tempting, DO NOT CALL FROM SIGNAL HANDLERS
 //      This function is not Async-Signal Safe.  It
 //      is thread safe
-ts::Errata
+swoc::Errata
 FileManager::rereadConfig()
 {
-  ts::Errata ret;
+  swoc::Errata ret;
 
   ConfigManager *rb;
   std::vector<ConfigManager *> changedFiles;
@@ -225,7 +226,8 @@ FileManager::rereadConfig()
       auto const &r = fileChanged(rb->getFileName(), rb->getConfigName());
 
       if (!r) {
-        std::for_each(r.begin(), r.end(), [&ret](auto &&e) { ret.push(e); });
+        ret.note("Errors while reloading configurations.");
+        ret.note(r);
       }
 
       changedFiles.push_back(rb);
@@ -265,7 +267,10 @@ FileManager::rereadConfig()
   for (size_t i = 0; i < n; i++) {
     if (std::find(changedFiles.begin(), changedFiles.end(), parentFileNeedChange[i]) == changedFiles.end()) {
       if (auto const &r = fileChanged(parentFileNeedChange[i]->getFileName(), parentFileNeedChange[i]->getConfigName()); !r) {
-        std::for_each(r.begin(), r.end(), [&ret](auto &&e) { ret.push(e); });
+        if (ret.empty()) {
+          ret.note("Error while handling parent file name changed.");
+        }
+        ret.note(r);
       }
     }
   }
@@ -277,13 +282,19 @@ FileManager::rereadConfig()
   if (found && enabled) {
     if (auto const &r = fileChanged("proxy.config.body_factory.template_sets_dir", "proxy.config.body_factory.template_sets_dir");
         !r) {
-      std::for_each(r.begin(), r.end(), [&ret](auto &&e) { ret.push(e); });
+      if (ret.empty()) {
+        ret.note("Error while loading body factory templates");
+      }
+      ret.note(r);
     }
   }
 
   if (auto const &r = fileChanged("proxy.config.ssl.server.ticket_key.filename", "proxy.config.ssl.server.ticket_key.filename");
       !r) {
-    std::for_each(r.begin(), r.end(), [&ret](auto &&e) { ret.push(e); });
+    if (ret.empty()) {
+      ret.note("Error while loading ticket keys");
+    }
+    ret.note(r);
   }
 
   return ret;
@@ -325,7 +336,7 @@ FileManager::configFileChild(const char *parent, const char *child)
 }
 
 auto
-FileManager::get_files_registry_rpc_endpoint(std::string_view const &id, YAML::Node const &params) -> ts::Rv<YAML::Node>
+FileManager::get_files_registry_rpc_endpoint(std::string_view const &id, YAML::Node const &params) -> swoc::Rv<YAML::Node>
 {
   // If any error, the rpc manager will catch it and respond with it.
   YAML::Node configs{YAML::NodeType::Sequence};
diff --git a/src/mgmt/rpc/CMakeLists.txt b/src/mgmt/rpc/CMakeLists.txt
index f9d5674405..36446217b7 100644
--- a/src/mgmt/rpc/CMakeLists.txt
+++ b/src/mgmt/rpc/CMakeLists.txt
@@ -38,8 +38,14 @@ add_library(ts::jsonrpc_server ALIAS jsonrpc_server)
 target_link_libraries(jsonrpc_server PUBLIC ts::jsonrpc_protocol)
 
 add_library(
-  rpcpublichandlers STATIC handlers/common/RecordsUtils.cc handlers/config/Configuration.cc handlers/records/Records.cc
-                           handlers/storage/Storage.cc handlers/server/Server.cc handlers/plugins/Plugins.cc
+  rpcpublichandlers STATIC
+  handlers/common/ErrorUtils.cc
+  handlers/common/RecordsUtils.cc
+  handlers/config/Configuration.cc
+  handlers/records/Records.cc
+  handlers/storage/Storage.cc
+  handlers/server/Server.cc
+  handlers/plugins/Plugins.cc
 )
 add_library(ts::rpcpublichandlers ALIAS rpcpublichandlers)
 
@@ -51,7 +57,9 @@ target_link_libraries(
 
 if(BUILD_TESTING)
   add_executable(test_jsonrpc jsonrpc/unit_tests/unit_test_main.cc jsonrpc/unit_tests/test_basic_protocol.cc)
-  target_link_libraries(test_jsonrpc ts::tsutil catch2::catch2 ts::jsonrpc_protocol libswoc::libswoc)
+  target_link_libraries(
+    test_jsonrpc ts::tsutil catch2::catch2 ts::rpcpublichandlers ts::jsonrpc_protocol libswoc::libswoc
+  )
   add_test(NAME test_jsonrpc COMMAND test_jsonrpc)
 
   add_executable(
diff --git a/src/mgmt/rpc/handlers/common/ErrorUtils.cc b/src/mgmt/rpc/handlers/common/ErrorUtils.cc
new file mode 100644
index 0000000000..2b9bcad7d9
--- /dev/null
+++ b/src/mgmt/rpc/handlers/common/ErrorUtils.cc
@@ -0,0 +1,69 @@
+/**
+   @section license License
+
+  Licensed to the Apache Software Foundation (ASF) under one
+  or more contributor license agreements.  See the NOTICE file
+  distributed with this work for additional information
+  regarding copyright ownership.  The ASF licenses this file
+  to you under the Apache License, Version 2.0 (the
+  "License"); you may not use this file except in compliance
+  with the License.  You may obtain a copy of the License at
+
+  http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+*/
+#include "mgmt/rpc/handlers/common/ErrorUtils.h"
+
+#include <system_error>
+#include <string>
+
+namespace
+{ // anonymous namespace
+
+struct RPCHandlerLogicErrorCategory : std::error_category {
+  const char *name() const noexcept override;
+  std::string message(int ev) const override;
+};
+
+const char *
+RPCHandlerLogicErrorCategory::name() const noexcept
+{
+  return "rpc_handler_logic_error";
+}
+std::string
+RPCHandlerLogicErrorCategory::message(int ev) const
+{
+  switch (static_cast<rpc::handlers::errors::Codes>(ev)) {
+  case rpc::handlers::errors::Codes::CONFIGURATION:
+    return {"Configuration handling error."};
+  case rpc::handlers::errors::Codes::METRIC:
+    return {"Metric handling error."};
+  case rpc::handlers::errors::Codes::RECORD:
+    return {"Record handling error."};
+  case rpc::handlers::errors::Codes::SERVER:
+    return {"Server handling error."};
+  case rpc::handlers::errors::Codes::STORAGE:
+    return {"Storage handling error."};
+  case rpc::handlers::errors::Codes::PLUGIN:
+    return {"Plugin handling error."};
+  default:
+    return "Generic handling error: " + std::to_string(ev);
+  }
+}
+
+const RPCHandlerLogicErrorCategory rpcHandlerLogicErrorCategory{};
+} // anonymous namespace
+
+namespace rpc::handlers::errors
+{
+std::error_code
+make_error_code(rpc::handlers::errors::Codes e)
+{
+  return {static_cast<int>(e), rpcHandlerLogicErrorCategory};
+}
+} // namespace rpc::handlers::errors
diff --git a/src/mgmt/rpc/handlers/config/Configuration.cc b/src/mgmt/rpc/handlers/config/Configuration.cc
index 773532553d..9a0a0b80e0 100644
--- a/src/mgmt/rpc/handlers/config/Configuration.cc
+++ b/src/mgmt/rpc/handlers/config/Configuration.cc
@@ -102,10 +102,10 @@ namespace
   }
 } // namespace
 
-ts::Rv<YAML::Node>
+swoc::Rv<YAML::Node>
 set_config_records(std::string_view const &id, YAML::Node const &params)
 {
-  ts::Rv<YAML::Node> resp;
+  swoc::Rv<YAML::Node> resp;
 
   // we need the type and the update type for now.
   using LookupContext = std::tuple<RecDataT, RecCheckT, const char *, RecUpdateT>;
@@ -115,7 +115,7 @@ set_config_records(std::string_view const &id, YAML::Node const &params)
     try {
       info = kv.as<SetRecordCmdInfo>();
     } catch (YAML::Exception const &ex) {
-      resp.errata().push({err::RecordError::RECORD_NOT_FOUND});
+      resp.errata().assign(std::error_code{errors::Codes::RECORD}).note("{}", std::error_code{err::RecordError::RECORD_NOT_FOUND});
       continue;
     }
 
@@ -139,7 +139,7 @@ set_config_records(std::string_view const &id, YAML::Node const &params)
 
     // make sure if exist. If not, we stop it and do not keep forward.
     if (ret != REC_ERR_OKAY) {
-      resp.errata().push({err::RecordError::RECORD_NOT_FOUND});
+      resp.errata().assign(std::error_code{errors::Codes::RECORD}).note("{}", std::error_code{err::RecordError::RECORD_NOT_FOUND});
       continue;
     }
 
@@ -148,7 +148,9 @@ set_config_records(std::string_view const &id, YAML::Node const &params)
 
     // run the check only if we have something to check against it.
     if (pattern != nullptr && utils::recordValidityCheck(info.value.c_str(), checkType, pattern) == false) {
-      resp.errata().push({err::RecordError::VALIDITY_CHECK_ERROR});
+      resp.errata()
+        .assign(std::error_code{errors::Codes::RECORD})
+        .note("{}", std::error_code{err::RecordError::VALIDITY_CHECK_ERROR});
       continue;
     }
 
@@ -173,7 +175,7 @@ set_config_records(std::string_view const &id, YAML::Node const &params)
       updatedRecord[utils::RECORD_UPDATE_TYPE_KEY] = std::to_string(updateType);
       resp.result().push_back(updatedRecord);
     } else {
-      resp.errata().push({err::RecordError::GENERAL_ERROR});
+      resp.errata().assign(std::error_code{errors::Codes::RECORD}).note("{}", std::error_code{err::RecordError::GENERAL_ERROR});
       continue;
     }
   }
@@ -181,17 +183,17 @@ set_config_records(std::string_view const &id, YAML::Node const &params)
   return resp;
 }
 
-ts::Rv<YAML::Node>
+swoc::Rv<YAML::Node>
 reload_config(std::string_view const &id, YAML::Node const &params)
 {
   ts::Metrics &metrics    = ts::Metrics::instance();
   static auto reconf_time = metrics.lookup("proxy.process.proxy.reconfigure_time");
   static auto reconf_req  = metrics.lookup("proxy.process.proxy.reconfigure_required");
-  ts::Rv<YAML::Node> resp;
+  swoc::Rv<YAML::Node> resp;
   Debug("RPC", "invoke plugin callbacks");
   // if there is any error, report it back.
-  if (auto err = FileManager::instance().rereadConfig(); err.size()) {
-    resp = err;
+  if (auto err = FileManager::instance().rereadConfig(); !err.empty()) {
+    resp.note(err);
   }
   // If any callback was register(TSMgmtUpdateRegister) for config notifications, then it will be eventually notify.
   FileManager::instance().invokeConfigPluginCallbacks();
diff --git a/src/mgmt/rpc/handlers/plugins/Plugins.cc b/src/mgmt/rpc/handlers/plugins/Plugins.cc
index b5e130ac3a..9cd4eb565e 100644
--- a/src/mgmt/rpc/handlers/plugins/Plugins.cc
+++ b/src/mgmt/rpc/handlers/plugins/Plugins.cc
@@ -56,7 +56,7 @@ namespace rpc::handlers::plugins
 {
 namespace err = rpc::handlers::errors;
 
-ts::Rv<YAML::Node>
+swoc::Rv<YAML::Node>
 plugin_send_basic_msg(std::string_view const &id, YAML::Node const &params)
 {
   // The rpc could be ready before plugins are initialized.
@@ -65,7 +65,7 @@ plugin_send_basic_msg(std::string_view const &id, YAML::Node const &params)
     return err::make_errata(err::Codes::PLUGIN, "Plugin is not yet ready to handle any messages.");
   }
 
-  ts::Rv<YAML::Node> resp;
+  swoc::Rv<YAML::Node> resp;
   try {
     // keep the data.
     PluginMsgInfo info = params.as<PluginMsgInfo>();
diff --git a/src/mgmt/rpc/handlers/records/Records.cc b/src/mgmt/rpc/handlers/records/Records.cc
index a1f3f809f9..de49f8aae5 100644
--- a/src/mgmt/rpc/handlers/records/Records.cc
+++ b/src/mgmt/rpc/handlers/records/Records.cc
@@ -204,7 +204,7 @@ namespace rpc::handlers::records
 {
 namespace err = rpc::handlers::errors;
 
-ts::Rv<YAML::Node>
+swoc::Rv<YAML::Node>
 lookup_records(std::string_view const &id, YAML::Node const &params)
 {
   // TODO: we may want to deal with our own object instead of a node here.
@@ -247,19 +247,19 @@ lookup_records(std::string_view const &id, YAML::Node const &params)
   return resp;
 }
 
-ts::Rv<YAML::Node>
+swoc::Rv<YAML::Node>
 clear_all_metrics_records(std::string_view const &id, YAML::Node const &params)
 {
   using namespace rpc::handlers::records::utils;
-  ts::Rv<YAML::Node> resp;
+  swoc::Rv<YAML::Node> resp;
   if (RecResetStatRecord(RECT_NULL, true) != REC_ERR_OKAY) {
-    return ts::Errata{rpc::handlers::errors::RecordError::RECORD_WRITE_ERROR};
+    return swoc::Errata{std::error_code{errors::Codes::METRIC}, "Failed to clear stats"};
   }
 
   return resp;
 }
 
-ts::Rv<YAML::Node>
+swoc::Rv<YAML::Node>
 clear_metrics_records(std::string_view const &id, YAML::Node const &params)
 {
   using namespace rpc::handlers::records::utils;
diff --git a/src/mgmt/rpc/handlers/server/Server.cc b/src/mgmt/rpc/handlers/server/Server.cc
index e6639cc6dd..8e74ed3098 100644
--- a/src/mgmt/rpc/handlers/server/Server.cc
+++ b/src/mgmt/rpc/handlers/server/Server.cc
@@ -79,10 +79,10 @@ set_server_drain(bool drain)
   metrics[drain_id].store(TSSystemState::is_draining() ? 1 : 0);
 }
 
-ts::Rv<YAML::Node>
+swoc::Rv<YAML::Node>
 server_start_drain(std::string_view const &id, YAML::Node const &params)
 {
-  ts::Rv<YAML::Node> resp;
+  swoc::Rv<YAML::Node> resp;
   try {
     if (!params.IsNull()) {
       DrainInfo di = params.as<DrainInfo>();
@@ -93,23 +93,23 @@ server_start_drain(std::string_view const &id, YAML::Node const &params)
     if (!is_server_draining()) {
       set_server_drain(true);
     } else {
-      resp.errata().push(err::make_errata(err::Codes::SERVER, "Server already draining."));
+      resp.errata().assign(std::error_code{errors::Codes::SERVER}).note("Server already draining.");
     }
   } catch (std::exception const &ex) {
     Debug("rpc.handler.server", "Got an error DrainInfo decoding: %s", ex.what());
-    resp.errata().push(err::make_errata(err::Codes::SERVER, "Error found during server drain: {}", ex.what()));
+    resp.errata().assign(std::error_code{errors::Codes::SERVER}).note("Error found during server drain: {}", ex.what());
   }
   return resp;
 }
 
-ts::Rv<YAML::Node>
+swoc::Rv<YAML::Node>
 server_stop_drain(std::string_view const &id, [[maybe_unused]] YAML::Node const &params)
 {
-  ts::Rv<YAML::Node> resp;
+  swoc::Rv<YAML::Node> resp;
   if (is_server_draining()) {
     set_server_drain(false);
   } else {
-    resp.errata().push(err::make_errata(err::Codes::SERVER, "Server is not draining."));
+    resp.errata().assign(std::error_code{errors::Codes::SERVER}).note("Server is not draining.");
   }
 
   return resp;
diff --git a/src/mgmt/rpc/handlers/storage/Storage.cc b/src/mgmt/rpc/handlers/storage/Storage.cc
index 10619caab6..0a66c7f500 100644
--- a/src/mgmt/rpc/handlers/storage/Storage.cc
+++ b/src/mgmt/rpc/handlers/storage/Storage.cc
@@ -57,10 +57,10 @@ namespace rpc::handlers::storage
 {
 namespace err = rpc::handlers::errors;
 
-ts::Rv<YAML::Node>
+swoc::Rv<YAML::Node>
 set_storage_offline(std::string_view const &id, YAML::Node const &params)
 {
-  ts::Rv<YAML::Node> resp;
+  swoc::Rv<YAML::Node> resp;
 
   for (auto &&it : params) {
     std::string device = it.as<std::string>();
@@ -75,16 +75,18 @@ set_storage_offline(std::string_view const &id, YAML::Node const &params)
       n["has_online_storage_left"] = ret ? "true" : "false";
       resp.result().push_back(std::move(n));
     } else {
-      resp.errata().push(err::make_errata(err::Codes::STORAGE, "Passed device:'{}' does not match any defined storage", device));
+      resp.errata()
+        .assign(std::error_code{errors::Codes::STORAGE})
+        .note("Passed device: '{}' does not match any defined storage", device);
     }
   }
   return resp;
 }
 
-ts::Rv<YAML::Node>
+swoc::Rv<YAML::Node>
 get_storage_status(std::string_view const &id, YAML::Node const &params)
 {
-  ts::Rv<YAML::Node> resp;
+  swoc::Rv<YAML::Node> resp;
 
   for (auto &&it : params) {
     std::string device = it.as<std::string>();
@@ -93,7 +95,9 @@ get_storage_status(std::string_view const &id, YAML::Node const &params)
     if (d) {
       resp.result().push_back(*d);
     } else {
-      resp.errata().push(err::make_errata(err::Codes::STORAGE, "Passed device:'{}' does not match any defined storage", device));
+      resp.errata()
+        .assign(std::error_code{errors::Codes::STORAGE})
+        .note("Passed device: '{}' does not match any defined storage", device);
     }
   }
   return resp;
diff --git a/src/mgmt/rpc/jsonrpc/Context.cc b/src/mgmt/rpc/jsonrpc/Context.cc
index 4c7d790691..f4f19682f4 100644
--- a/src/mgmt/rpc/jsonrpc/Context.cc
+++ b/src/mgmt/rpc/jsonrpc/Context.cc
@@ -22,10 +22,10 @@
 namespace rpc
 {
 // --- Call Context impl
-ts::Errata
+swoc::Errata
 Context::Auth::is_blocked(TSRPCHandlerOptions const &options) const
 {
-  ts::Errata out;
+  swoc::Errata out;
   // check every registered callback and see if they have something to say. Then report back to the manager
   for (auto &&check : _checkers) {
     check(options, out);
diff --git a/src/mgmt/rpc/jsonrpc/JsonRPCManager.cc b/src/mgmt/rpc/jsonrpc/JsonRPCManager.cc
index b05e35279c..dbe695934b 100644
--- a/src/mgmt/rpc/jsonrpc/JsonRPCManager.cc
+++ b/src/mgmt/rpc/jsonrpc/JsonRPCManager.cc
@@ -27,6 +27,7 @@
 #include <condition_variable>
 
 #include <swoc/swoc_meta.h>
+
 #include "mgmt/rpc/jsonrpc/json/YAMLCodec.h"
 
 namespace
@@ -57,15 +58,16 @@ RPCRegistryInfo core_ats_rpc_service_provider_handle = {
 // plugin rpc handling variables.
 std::mutex g_rpcHandlingMutex;
 std::condition_variable g_rpcHandlingCompletion;
-ts::Rv<YAML::Node> g_rpcHandlerResponseData;
+swoc::Rv<YAML::Node> g_rpcHandlerResponseData;
 bool g_rpcHandlerProcessingCompleted{false};
 
 // --- Helpers
-std::pair<ts::Errata, error::RPCErrorCode>
+swoc::Errata
 check_for_blockers(Context const &ctx, TSRPCHandlerOptions const &options)
 {
-  if (auto err = ctx.get_auth().is_blocked(options); !err.isOK()) {
-    return {err, error::RPCErrorCode::Unauthorized};
+  if (auto err = ctx.get_auth().is_blocked(options); !err.is_ok()) {
+    return std::move(err.note(swoc::Errata(std::error_code(unsigned(error::RPCErrorCode::Unauthorized), std::generic_category()),
+                                           ERRATA_ERROR, swoc::Errata::AUTO)));
   }
   return {};
 }
@@ -80,7 +82,7 @@ JsonRPCManager::Dispatcher::register_service_descriptor_handler()
 {
   if (!this->add_handler<Dispatcher::Method, MethodHandlerSignature>(
         "show_registered_handlers",
-        [this](std::string_view const &id, const YAML::Node &req) -> ts::Rv<YAML::Node> {
+        [this](std::string_view const &id, const YAML::Node &req) -> swoc::Rv<YAML::Node> {
           return show_registered_handlers(id, req);
         },
         &core_ats_rpc_service_provider_handle, {{NON_RESTRICTED_API}})) {
@@ -89,7 +91,9 @@ JsonRPCManager::Dispatcher::register_service_descriptor_handler()
 
   if (!this->add_handler<Dispatcher::Method, MethodHandlerSignature>(
         "get_service_descriptor",
-        [this](std::string_view const &id, const YAML::Node &req) -> ts::Rv<YAML::Node> { return get_service_descriptor(id, req); },
+        [this](std::string_view const &id, const YAML::Node &req) -> swoc::Rv<YAML::Node> {
+          return get_service_descriptor(id, req);
+        },
         &core_ats_rpc_service_provider_handle, {{NON_RESTRICTED_API}})) {
     Warning("Handler already registered.");
   }
@@ -108,10 +112,10 @@ JsonRPCManager::Dispatcher::dispatch(Context const &ctx, specs::RPCRequestInfo c
   }
 
   // We have got a valid handler, we will now check if the context holds any restriction for this handler to be called.
-  if (auto &&[errata, ec] = check_for_blockers(ctx, handler.get_options()); !errata.isOK()) {
+  if (auto errata = check_for_blockers(ctx, handler.get_options()); !errata.is_ok()) {
     specs::RPCResponseInfo resp{request.id};
     resp.error.ec   = ec;
-    resp.error.data = errata;
+    resp.error.data = std::move(errata);
     return resp;
   }
 
@@ -152,13 +156,13 @@ JsonRPCManager::Dispatcher::invoke_method_handler(JsonRPCManager::Dispatcher::In
   specs::RPCResponseInfo response{request.id};
 
   try {
-    auto const &rv = handler.invoke(request);
+    auto rv = handler.invoke(request);
 
-    if (rv.isOK()) {
+    if (rv.is_ok()) {
       response.callResult.result = rv.result();
     } else {
       // if we have some errors to log, then include it.
-      response.callResult.errata = rv.errata();
+      response.callResult.errata = std::move(rv.errata());
     }
   } catch (std::exception const &e) {
     Debug(logTag, "Oops, something happened during the callback invocation: %s", e.what());
@@ -238,6 +242,7 @@ JsonRPCManager::handle_call(Context const &ctx, std::string const &request)
       } else {
         // If the request was marked as an error(decode error), we still need to send the error back, so we save it.
         specs::RPCResponseInfo resp{req.id};
+        // resp.error.assign(swoc::Errata(decode_error));
         resp.error.ec = decode_error;
         response.add_message(std::move(resp));
       }
@@ -250,20 +255,22 @@ JsonRPCManager::handle_call(Context const &ctx, std::string const &request)
       resp = Encoder::encode(response);
       Debug(logTagMsg, "<-- JSONRPC Response\n '%s'", (*resp).c_str());
     }
+
     return resp;
   } catch (std::exception const &ex) {
     ec = error::RPCErrorCode::INTERNAL_ERROR;
   }
+
   specs::RPCResponseInfo resp;
   resp.error.ec = ec;
   return {Encoder::encode(resp)};
 }
 
 // ---------------------------- InternalHandler ---------------------------------
-inline ts::Rv<YAML::Node>
+inline swoc::Rv<YAML::Node>
 JsonRPCManager::Dispatcher::InternalHandler::invoke(specs::RPCRequestInfo const &request) const
 {
-  ts::Rv<YAML::Node> ret;
+  swoc::Rv<YAML::Node> ret;
   std::visit(swoc::meta::vary{[](std::monostate) -> void { /* no op */ },
                               [&request](Notification const &handler) -> void {
                                 // Notification handler call. Ignore response, there is no completion cv check in here basically
@@ -284,11 +291,11 @@ JsonRPCManager::Dispatcher::InternalHandler::invoke(specs::RPCRequestInfo const
                                 std::unique_lock<std::mutex> lock(g_rpcHandlingMutex);
                                 g_rpcHandlingCompletion.wait(lock, []() { return g_rpcHandlerProcessingCompleted; });
                                 g_rpcHandlerProcessingCompleted = false;
-                                // seems to be done, set the response. As the response data is a ts::Rv this will handle both,
+                                // seems to be done, set the response. As the response data is a swoc::Rv this will handle both,
                                 // error and non error cases.
-                                ret = g_rpcHandlerResponseData;
+                                ret = std::move(g_rpcHandlerResponseData);
                                 // clean up the shared data.
-                                g_rpcHandlerResponseData.clear();
+                                //                                g_rpcHandlerResponseData.clear(); // moved so no cleanup?
                                 lock.unlock();
                               }},
              this->_func);
@@ -310,10 +317,10 @@ JsonRPCManager::Dispatcher::InternalHandler::is_method() const
   return false;
 }
 
-ts::Rv<YAML::Node>
+swoc::Rv<YAML::Node>
 JsonRPCManager::Dispatcher::show_registered_handlers(std::string_view const &, const YAML::Node &)
 {
-  ts::Rv<YAML::Node> resp;
+  swoc::Rv<YAML::Node> resp;
   std::lock_guard<std::mutex> lock(_mutex);
   for (auto const &[name, handler] : _handlers) {
     std::string const &key = handler.is_method() ? RPC_SERVICE_METHODS_KEY : RPC_SERVICE_NOTIFICATIONS_KEY;
@@ -324,7 +331,7 @@ JsonRPCManager::Dispatcher::show_registered_handlers(std::string_view const &, c
 
 // -----------------------------------------------------------------------------
 // This jsonrpc handler can provides a service descriptor for the RPC
-ts::Rv<YAML::Node>
+swoc::Rv<YAML::Node>
 JsonRPCManager::Dispatcher::get_service_descriptor(std::string_view const &, const YAML::Node &)
 {
   YAML::Node rpcService;
diff --git a/src/mgmt/rpc/jsonrpc/unit_tests/test_basic_protocol.cc b/src/mgmt/rpc/jsonrpc/unit_tests/test_basic_protocol.cc
index 117c597f20..68e1146751 100644
--- a/src/mgmt/rpc/jsonrpc/unit_tests/test_basic_protocol.cc
+++ b/src/mgmt/rpc/jsonrpc/unit_tests/test_basic_protocol.cc
@@ -28,8 +28,6 @@
 
 namespace
 {
-const int ErratId{1};
-
 // Not using the singleton logic.
 struct JsonRpcUnitTest : rpc::JsonRPCManager {
   JsonRpcUnitTest() : JsonRPCManager() {}
@@ -60,16 +58,20 @@ struct JsonRpcUnitTest : rpc::JsonRPCManager {
 };
 
 enum class TestErrors { ERR1 = 9999, ERR2 };
-inline ts::Rv<YAML::Node>
+static const std::error_code ERR1{ts::make_errno_code(9999)};
+static const std::error_code ERR2{ts::make_errno_code(10000)};
+static std::string_view err{"Just an error message to add more meaning to the failure"};
+
+inline swoc::Rv<YAML::Node>
 test_callback_ok_or_error(std::string_view const &id, YAML::Node const &params)
 {
-  ts::Rv<YAML::Node> resp;
+  swoc::Rv<YAML::Node> resp;
 
   // play with the req.id if needed.
   if (YAML::Node n = params["return_error"]) {
     auto yesOrNo = n.as<std::string>();
     if (yesOrNo == "yes") {
-      resp.errata().push(ErratId, static_cast<int>(TestErrors::ERR1), "Just an error message to add more meaning to the failure");
+      resp.errata().assign(ERR1).note(err);
     } else {
       resp.result()["ran"] = "ok";
     }
@@ -334,12 +336,12 @@ TEST_CASE("Basic test with member functions(add, remove)", "[basic][member_funct
     {
       return rpc.add_method_handler(
         "member_function",
-        [this](std::string_view const &id, const YAML::Node &req) -> ts::Rv<YAML::Node> { return test(id, req); });
+        [this](std::string_view const &id, const YAML::Node &req) -> swoc::Rv<YAML::Node> { return test(id, req); });
     }
-    ts::Rv<YAML::Node>
+    swoc::Rv<YAML::Node>
     test(std::string_view const &id, const YAML::Node &req)
     {
-      ts::Rv<YAML::Node> resp;
+      swoc::Rv<YAML::Node> resp;
       resp.result() = "grand!";
       return resp;
     }
@@ -379,10 +381,10 @@ TEST_CASE("Test Dispatcher rpc method", "[dispatcher]")
           R"({"jsonrpc": "2.0", "result": {"methods": ["get_service_descriptor", "show_registered_handlers"]}, "id": "AbC"})");
 }
 
-[[maybe_unused]] static ts::Rv<YAML::Node>
+[[maybe_unused]] static swoc::Rv<YAML::Node>
 subtract(std::string_view const &id, YAML::Node const &numbers)
 {
-  ts::Rv<YAML::Node> res;
+  swoc::Rv<YAML::Node> res;
 
   if (numbers.Type() == YAML::NodeType::Sequence) {
     auto it   = numbers.begin();
@@ -402,10 +404,10 @@ subtract(std::string_view const &id, YAML::Node const &numbers)
   return res;
 }
 
-[[maybe_unused]] static ts::Rv<YAML::Node>
+[[maybe_unused]] static swoc::Rv<YAML::Node>
 sum(std::string_view const &id, YAML::Node const &params)
 {
-  ts::Rv<YAML::Node> res;
+  swoc::Rv<YAML::Node> res;
   int total{0};
   for (auto n : params) {
     total += n.as<int>();
@@ -414,10 +416,10 @@ sum(std::string_view const &id, YAML::Node const &params)
   return res;
 }
 
-[[maybe_unused]] static ts::Rv<YAML::Node>
+[[maybe_unused]] static swoc::Rv<YAML::Node>
 get_data(std::string_view const &id, YAML::Node const &params)
 {
-  ts::Rv<YAML::Node> res;
+  swoc::Rv<YAML::Node> res;
   res.result().push_back("hello");
   res.result().push_back("5");
   return res;
@@ -555,10 +557,10 @@ TEST_CASE("Handle un-handle handler's error", "[throw]")
   JsonRpcUnitTest rpc;
   SECTION("Basic exception thrown")
   {
-    REQUIRE(
-      rpc.add_method_handler("oops_i_did_it_again", [](std::string_view const &id, const YAML::Node &params) -> ts::Rv<YAML::Node> {
-        throw std::runtime_error("Oops, I did it again");
-      }));
+    REQUIRE(rpc.add_method_handler("oops_i_did_it_again",
+                                   [](std::string_view const &id, const YAML::Node &params) -> swoc::Rv<YAML::Node> {
+                                     throw std::runtime_error("Oops, I did it again");
+                                   }));
     const auto resp           = rpc.handle_call(R"({"jsonrpc": "2.0", "method": "oops_i_did_it_again", "id": "1"})");
     std::string_view expected = R"({"jsonrpc": "2.0", "error": {"code": 9, "message": "Error during execution"}, "id": "1"})";
     REQUIRE(*resp == expected);
@@ -570,10 +572,10 @@ TEST_CASE("Call registered method with no ID", "[no-id]")
   JsonRpcUnitTest rpc;
   SECTION("Basic test, no id on method call")
   {
-    REQUIRE(
-      rpc.add_method_handler("call_me_with_no_id", [](std::string_view const &id, const YAML::Node &params) -> ts::Rv<YAML::Node> {
-        throw std::runtime_error("Oops, I did it again");
-      }));
+    REQUIRE(rpc.add_method_handler("call_me_with_no_id",
+                                   [](std::string_view const &id, const YAML::Node &params) -> swoc::Rv<YAML::Node> {
+                                     throw std::runtime_error("Oops, I did it again");
+                                   }));
     const auto resp           = rpc.handle_call(R"({"jsonrpc": "2.0", "method": "call_me_with_no_id"})");
     std::string_view expected = R"({"jsonrpc": "2.0", "error": {"code": -32600, "message": "Invalid Request"}})";
     REQUIRE(*resp == expected);
diff --git a/src/mgmt/rpc/server/IPCSocketServer.cc b/src/mgmt/rpc/server/IPCSocketServer.cc
index 3b6e3b568f..f476bb0183 100644
--- a/src/mgmt/rpc/server/IPCSocketServer.cc
+++ b/src/mgmt/rpc/server/IPCSocketServer.cc
@@ -226,7 +226,7 @@ IPCSocketServer::run()
         rpc::Context ctx;
         // we want to make sure the peer's credentials are ok.
         ctx.get_auth().add_checker(
-          [&](TSRPCHandlerOptions const &opt, ts::Errata &errata) -> void { return late_check_peer_credentials(fd, opt, errata); });
+          [&](TSRPCHandlerOptions const &opt, swoc::Errata &errata) -> void { late_check_peer_credentials(fd, opt, errata); });
 
         if (auto response = rpc::JsonRPCManager::instance().handle_call(ctx, json); response) {
           // seems a valid response.
@@ -446,19 +446,23 @@ IPCSocketServer::Config::Config()
 }
 
 void
-IPCSocketServer::late_check_peer_credentials(int peedFd, TSRPCHandlerOptions const &options, ts::Errata &errata) const
+IPCSocketServer::late_check_peer_credentials(int peedFd, TSRPCHandlerOptions const &options, swoc::Errata &errata) const
 {
   swoc::LocalBufferWriter<256> w;
   // For privileged calls, ensure we have caller credentials and that the caller is privileged.
+  auto ecode = [](UnauthorizedErrorCode c) -> std::error_code {
+    return std::error_code(static_cast<unsigned>(c), std::generic_category());
+  };
+
   if (has_peereid() && options.auth.restricted) {
     uid_t euid = -1;
     gid_t egid = -1;
     if (get_peereid(peedFd, &euid, &egid) == -1) {
-      errata.push(1, static_cast<int>(UnauthorizedErrorCode::PEER_CREDENTIALS_ERROR),
-                  w.print("Error getting peer credentials: {}\0", swoc::bwf::Errno{}).data());
+      errata.assign(ecode(UnauthorizedErrorCode::PEER_CREDENTIALS_ERROR))
+        .note("Error getting peer credentials: {}", swoc::bwf::Errno{});
     } else if (euid != 0 && euid != geteuid()) {
-      errata.push(1, static_cast<int>(UnauthorizedErrorCode::PERMISSION_DENIED),
-                  w.print("Denied privileged API access for uid={} gid={}\0", euid, egid).data());
+      errata.assign(ecode(UnauthorizedErrorCode::PERMISSION_DENIED))
+        .note("Denied privileged API access for uid={} gid={}", euid, egid);
     }
   }
 }
diff --git a/src/mgmt/rpc/server/unit_tests/test_rpcserver.cc b/src/mgmt/rpc/server/unit_tests/test_rpcserver.cc
index c08183e34a..c28abd21bc 100644
--- a/src/mgmt/rpc/server/unit_tests/test_rpcserver.cc
+++ b/src/mgmt/rpc/server/unit_tests/test_rpcserver.cc
@@ -45,7 +45,7 @@
 #include "tscore/Layout.h"
 #include "iocore/utils/diags.i"
 
-#define DEFINE_JSONRPC_PROTO_FUNCTION(fn) ts::Rv<YAML::Node> fn(std::string_view const &id, const YAML::Node &params)
+#define DEFINE_JSONRPC_PROTO_FUNCTION(fn) swoc::Rv<YAML::Node> fn(std::string_view const &id, const YAML::Node &params)
 
 namespace fs = swoc::file;
 
@@ -127,7 +127,7 @@ RPCServerTestListener::~RPCServerTestListener() {}
 
 DEFINE_JSONRPC_PROTO_FUNCTION(some_foo) // id, params
 {
-  ts::Rv<YAML::Node> resp;
+  swoc::Rv<YAML::Node> resp;
   int dur{1};
   try {
     dur = params["duration"].as<int>();
@@ -309,7 +309,7 @@ random_string(std::string::size_type length)
 
 DEFINE_JSONRPC_PROTO_FUNCTION(do_nothing) // id, params, resp
 {
-  ts::Rv<YAML::Node> resp;
+  swoc::Rv<YAML::Node> resp;
   resp.result()["size"] = params["msg"].as<std::string>().size();
   return resp;
 }
diff --git a/src/proxy/CMakeLists.txt b/src/proxy/CMakeLists.txt
index 508ba7c1d8..6b25c6683d 100644
--- a/src/proxy/CMakeLists.txt
+++ b/src/proxy/CMakeLists.txt
@@ -47,7 +47,7 @@ endif()
 target_link_libraries(
   proxy
   PUBLIC ts::inkcache ts::inkevent ts::tsutil ts::tscore
-  PRIVATE ts::jsonrpc_protocol ts::inkutils ts::tsapibackend
+  PRIVATE ts::rpcpublichandlers ts::jsonrpc_protocol ts::inkutils ts::tsapibackend
 )
 
 add_subdirectory(hdrs)
diff --git a/src/proxy/HostStatus.cc b/src/proxy/HostStatus.cc
index 121770fbe9..9e8e7fb540 100644
--- a/src/proxy/HostStatus.cc
+++ b/src/proxy/HostStatus.cc
@@ -44,8 +44,8 @@ struct HostCmdInfo {
 
 } // namespace
 
-ts::Rv<YAML::Node> server_get_status(std::string_view const id, YAML::Node const &params);
-ts::Rv<YAML::Node> server_set_status(std::string_view const id, YAML::Node const &params);
+swoc::Rv<YAML::Node> server_get_status(std::string_view const id, YAML::Node const &params);
+swoc::Rv<YAML::Node> server_set_status(std::string_view const id, YAML::Node const &params);
 
 HostStatRec::HostStatRec()
   : status(TS_HOST_STATUS_UP),
@@ -419,11 +419,11 @@ template <> struct convert<HostCmdInfo> {
 } // namespace YAML
 
 // JSON-RPC method to retrieve host status information.
-ts::Rv<YAML::Node>
+swoc::Rv<YAML::Node>
 server_get_status(std::string_view id, YAML::Node const &params)
 {
   namespace err = rpc::handlers::errors;
-  ts::Rv<YAML::Node> resp;
+  swoc::Rv<YAML::Node> resp;
   YAML::Node statusList{YAML::NodeType::Sequence}, errorList{YAML::NodeType::Sequence};
 
   try {
@@ -470,12 +470,12 @@ server_get_status(std::string_view id, YAML::Node const &params)
 }
 
 // JSON-RPC method to mark up or down a host.
-ts::Rv<YAML::Node>
+swoc::Rv<YAML::Node>
 server_set_status(std::string_view id, YAML::Node const &params)
 {
   Debug("host_statuses", "id=%s", id.data());
   namespace err = rpc::handlers::errors;
-  ts::Rv<YAML::Node> resp;
+  swoc::Rv<YAML::Node> resp;
 
   try {
     if (!params.IsNull()) {
@@ -489,7 +489,7 @@ server_set_status(std::string_view id, YAML::Node const &params)
         hs.setHostStatus(name.c_str(), cmdInfo.type, cmdInfo.time, cmdInfo.reasonType);
       }
     } else {
-      resp.errata().push(err::make_errata(err::Codes::SERVER, "Invalid input parameters, null"));
+      resp.errata().assign(std::error_code{rpc::handlers::errors::Codes::SERVER}).note("Invalid input parameters, null");
     }
 
     // schedule a write to the persistent store.
@@ -497,7 +497,9 @@ server_set_status(std::string_view id, YAML::Node const &params)
     eventProcessor.schedule_imm(new HostStatusSync, ET_TASK);
   } catch (std::exception const &ex) {
     Debug("host_statuses", "Got an error HostCmdInfo decoding: %s", ex.what());
-    resp.errata().push(err::make_errata(err::Codes::SERVER, "Error found during host status set: {}", ex.what()));
+    resp.errata()
+      .assign(std::error_code{rpc::handlers::errors::Codes::SERVER})
+      .note("Error found during host status set: {}", ex.what());
   }
   return resp;
 }
diff --git a/src/proxy/http/HttpConfig.cc b/src/proxy/http/HttpConfig.cc
index aadc77e8a9..1cfde695b2 100644
--- a/src/proxy/http/HttpConfig.cc
+++ b/src/proxy/http/HttpConfig.cc
@@ -22,6 +22,8 @@
   limitations under the License.
  */
 
+#include <deque>
+
 #include "tscore/ink_config.h"
 #include "tscore/Filenames.h"
 #include "tscore/Tokenizer.h"
diff --git a/src/traffic_cache_tool/CacheTool.cc b/src/traffic_cache_tool/CacheTool.cc
index 6b187e2cd5..8d1b07652f 100644
--- a/src/traffic_cache_tool/CacheTool.cc
+++ b/src/traffic_cache_tool/CacheTool.cc
@@ -47,6 +47,7 @@
 
 using swoc::MemSpan;
 using swoc::Errata;
+using ts::make_errno_code;
 
 using ts::Bytes;
 using ts::Megabytes;
diff --git a/src/tscore/CMakeLists.txt b/src/tscore/CMakeLists.txt
index 68ed20e878..b7722e99a4 100644
--- a/src/tscore/CMakeLists.txt
+++ b/src/tscore/CMakeLists.txt
@@ -39,7 +39,6 @@ add_library(
   CryptoHash.cc
   Diags.cc
   Encoding.cc
-  Errata.cc
   EventNotify.cc
   Extendible.cc
   FrequencyCounter.cc
@@ -145,7 +144,6 @@ if(BUILD_TESTING)
     unit_tests/test_AcidPtr.cc
     unit_tests/test_ArgParser.cc
     unit_tests/test_CryptoHash.cc
-    unit_tests/test_Errata.cc
     unit_tests/test_Extendible.cc
     unit_tests/test_Encoding.cc
     unit_tests/test_FrequencyCounter.cc
diff --git a/src/tscore/Errata.cc b/src/tscore/Errata.cc
deleted file mode 100644
index ded3bf5e80..0000000000
--- a/src/tscore/Errata.cc
+++ /dev/null
@@ -1,269 +0,0 @@
-/** @file
-    Errata implementation.
-
-    @section license License
-
-    Licensed to the Apache Software Foundation (ASF) under one
-    or more contributor license agreements.  See the NOTICE file
-    distributed with this work for additional information
-    regarding copyright ownership.  The ASF licenses this file
-    to you under the Apache License, Version 2.0 (the
-    "License"); you may not use this file except in compliance
-    with the License.  You may obtain a copy of the License at
-
-    http://www.apache.org/licenses/LICENSE-2.0
-
-    Unless required by applicable law or agreed to in writing, software
-    distributed under the License is distributed on an "AS IS" BASIS,
-    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-    See the License for the specific language governing permissions and
-    limitations under the License.
- */
-
-#include "tscore/Errata.h"
-
-#include <iostream>
-#include <sstream>
-#include <iomanip>
-#include <algorithm>
-#include <memory.h>
-
-namespace ts
-{
-/** List of sinks for abandoned erratum.
- */
-namespace
-{
-  std::deque<Errata::Sink::Handle> Sink_List;
-}
-
-std::string const Errata::DEFAULT_GLUE("\n");
-Errata::Message const Errata::NIL_MESSAGE;
-Errata::Code Errata::Message::Default_Code                               = 0;
-Errata::Message::SuccessTest const Errata::Message::DEFAULT_SUCCESS_TEST = &Errata::Message::isCodeZero;
-Errata::Message::SuccessTest Errata::Message::Success_Test               = Errata::Message::DEFAULT_SUCCESS_TEST;
-
-bool
-Errata::Message::isCodeZero(Message const &msg)
-{
-  return msg.m_code == 0;
-}
-
-void
-Errata::Data::push(Message const &msg)
-{
-  m_items.push_back(msg);
-}
-
-void
-Errata::Data::push(Message &&msg)
-{
-  m_items.push_back(std::move(msg));
-}
-
-Errata::Message const &
-Errata::Data::top() const
-{
-  return m_items.size() ? m_items.back() : NIL_MESSAGE;
-}
-
-inline Errata::Errata(ImpPtr const &ptr) : m_data(ptr) {}
-
-Errata::Data::~Data()
-{
-  if (m_log_on_delete) {
-    Errata tmp(ImpPtr(this)); // because client API requires a wrapper.
-    for (auto &f : Sink_List) {
-      (*f)(tmp);
-    }
-    tmp.m_data.release(); // don't delete this again.
-  }
-}
-
-Errata::Errata(self const &that) : m_data(that.m_data) {}
-
-Errata::Errata(self &&that) : m_data(that.m_data) {}
-
-Errata::Errata(std::string const &text)
-{
-  this->push(text);
-}
-
-Errata::Errata(Id id, std::string const &text)
-{
-  this->push(id, text);
-}
-
-Errata::~Errata() {}
-
-/*  This forces the errata to have a data object that only it references.
-    If we're sharing the data, clone. If there's no data, allocate.
-    This is used just before a write operation to have copy on write semantics.
- */
-Errata::Data *
-Errata::pre_write()
-{
-  if (m_data) {
-    if (m_data.use_count() > 1) {
-      m_data.reset(new Data(*m_data)); // clone current data
-    }
-  } else { // create new data
-    m_data.reset(new Data);
-  }
-  return m_data.get();
-}
-
-// Just create an instance if needed.
-Errata::Data const *
-Errata::instance()
-{
-  if (!m_data) {
-    m_data.reset(new Data);
-  }
-  return m_data.get();
-}
-
-Errata &
-Errata::push(Message const &msg)
-{
-  this->pre_write()->push(msg);
-  return *this;
-}
-
-Errata &
-Errata::push(Message &&msg)
-{
-  this->pre_write()->push(std::move(msg));
-  return *this;
-}
-
-Errata &
-Errata::operator=(self const &that)
-{
-  m_data = that.m_data;
-  return *this;
-}
-
-Errata &
-Errata::operator=(Message const &msg)
-{
-  // Avoid copy on write in the case where we discard.
-  if (!m_data || m_data.use_count() > 1) {
-    this->clear();
-    this->push(msg);
-  } else {
-    m_data->m_items.clear();
-    m_data->push(msg);
-  }
-  return *this;
-}
-
-Errata &
-Errata::operator=(self &&that)
-{
-  m_data = that.m_data;
-  return *this;
-}
-
-Errata &
-Errata::pull(self &that)
-{
-  if (that.m_data) {
-    this->pre_write();
-    m_data->m_items.insert(m_data->m_items.end(), that.m_data->m_items.begin(), that.m_data->m_items.end());
-    that.m_data->m_items.clear();
-  }
-  return *this;
-}
-
-void
-Errata::pop()
-{
-  if (m_data && m_data->size()) {
-    this->pre_write()->m_items.pop_front();
-  }
-  return;
-}
-
-void
-Errata::clear()
-{
-  m_data.reset(nullptr);
-}
-
-/*  We want to allow iteration on empty / nil containers because that's very
-    convenient for clients. We need only return the same value for begin()
-    and end() and everything works as expected.
-
-    However we need to be a bit more clever for VC 8.  It checks for
-    iterator compatibility, i.e. that the iterators are not
-    invalidated and that they are for the same container.  It appears
-    that default iterators are not compatible with anything.  So we
-    use static container for the nil data case.
- */
-static Errata::Container NIL_CONTAINER;
-
-Errata::iterator
-Errata::begin()
-{
-  return m_data ? m_data->m_items.rbegin() : NIL_CONTAINER.rbegin();
-}
-
-Errata::const_iterator
-Errata::begin() const
-{
-  return m_data ? static_cast<Data const &>(*m_data).m_items.rbegin() : static_cast<Container const &>(NIL_CONTAINER).rbegin();
-}
-
-Errata::iterator
-Errata::end()
-{
-  return m_data ? m_data->m_items.rend() : NIL_CONTAINER.rend();
-}
-
-Errata::const_iterator
-Errata::end() const
-{
-  return m_data ? static_cast<Data const &>(*m_data).m_items.rend() : static_cast<Container const &>(NIL_CONTAINER).rend();
-}
-
-void
-Errata::registerSink(Sink::Handle const &s)
-{
-  Sink_List.push_back(s);
-}
-
-std::ostream &
-Errata::write(std::ostream &out, int offset, int indent, int shift, char const *lead) const
-{
-  for (auto m : *this) {
-    if ((offset + indent) > 0) {
-      out << std::setw(indent + offset) << std::setfill(' ') << ((indent > 0 && lead) ? lead : " ");
-    }
-
-    out << m.m_id << " [" << m.m_code << "]: " << m.m_text << std::endl;
-    if (m.getErrata().size()) {
-      m.getErrata().write(out, offset, indent + shift, shift, lead);
-    }
-  }
-  return out;
-}
-
-size_t
-Errata::write(char *buff, size_t n, int offset, int indent, int shift, char const *lead) const
-{
-  std::ostringstream out;
-  std::string text;
-  this->write(out, offset, indent, shift, lead);
-  text = out.str();
-  memcpy(buff, text.data(), std::min(n, text.size()));
-  return text.size();
-}
-
-std::ostream &
-operator<<(std::ostream &os, Errata const &err)
-{
-  return err.write(os, 0, 0, 2, "> ");
-}
-
-} // namespace ts
diff --git a/src/tscore/unit_tests/test_Errata.cc b/src/tscore/unit_tests/test_Errata.cc
deleted file mode 100644
index f19273a782..0000000000
--- a/src/tscore/unit_tests/test_Errata.cc
+++ /dev/null
@@ -1,60 +0,0 @@
-/**
-  @file Test for Errata
-
-  @section license License
-
-  Licensed to the Apache Software Foundation (ASF) under one
-  or more contributor license agreements.  See the NOTICE file
-  distributed with this work for additional information
-  regarding copyright ownership.  The ASF licenses this file
-  to you under the Apache License, Version 2.0 (the
-  "License"); you may not use this file except in compliance
-  with the License.  You may obtain a copy of the License at
-
-      http://www.apache.org/licenses/LICENSE-2.0
-
-  Unless required by applicable law or agreed to in writing, software
-  distributed under the License is distributed on an "AS IS" BASIS,
-  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-  See the License for the specific language governing permissions and
-  limitations under the License.
-*/
-
-#include "catch.hpp"
-
-#include "tscore/Errata.h"
-
-TEST_CASE("Basic Errata with text only", "[errata]")
-{
-  ts::Errata err;
-  std::string text{"Some error text"};
-  err.push(text);
-  REQUIRE(err.isOK()); // as code is 0 by default.
-  REQUIRE(err.top().text() == text);
-}
-
-TEST_CASE("Basic Errata test with id and text", "[errata]")
-{
-  ts::Errata err;
-  int id{1};
-  std::string text{"Some error text"};
-
-  err.push(id, text);
-
-  REQUIRE(err.isOK()); // as code is 0 by default.
-  REQUIRE(err.top().text() == text);
-}
-
-TEST_CASE("Basic Errata test with id,code and text", "[errata]")
-{
-  ts::Errata err;
-  int id{1};
-  unsigned int code{2};
-  std::string text{"Some error text"};
-
-  err.push(id, code, text);
-
-  REQUIRE(!err.isOK()); // This should not be ok as code now is 2
-  REQUIRE(err.top().getCode() == code);
-  REQUIRE(err.top().text() == text);
-}
diff --git a/src/tsutil/CMakeLists.txt b/src/tsutil/CMakeLists.txt
index 0cd0ab8fd4..17f7f19b2d 100644
--- a/src/tsutil/CMakeLists.txt
+++ b/src/tsutil/CMakeLists.txt
@@ -37,6 +37,7 @@ set(TSUTIL_PUBLIC_HEADERS
     ${PROJECT_SOURCE_DIR}/include/tsutil/ts_meta.h
     ${PROJECT_SOURCE_DIR}/include/tsutil/ts_time_parser.h
     ${PROJECT_SOURCE_DIR}/include/tsutil/ts_unit_parser.h
+    ${PROJECT_SOURCE_DIR}/include/tsutil/ts_errata.h
 )
 add_library(
   tsutil
@@ -49,6 +50,7 @@ add_library(
   YamlCfg.cc
   ts_unit_parser.cc
   Regex.cc
+  ts_errata.cc
 )
 
 add_library(ts::tsutil ALIAS tsutil)
diff --git a/src/tsutil/ts_errata.cc b/src/tsutil/ts_errata.cc
new file mode 100644
index 0000000000..fc10b11eb8
--- /dev/null
+++ b/src/tsutil/ts_errata.cc
@@ -0,0 +1,34 @@
+/** @file
+
+    Utilities for @c swoc::Errata
+
+    @section license License
+
+    Licensed to the Apache Software Foundation (ASF) under one or more
+    contributor license agreements.  See the NOTICE file distributed with this
+    work for additional information regarding copyright ownership.  The ASF
+    licenses this file to you under the Apache License, Version 2.0 (the
+    "License"); you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+    License for the specific language governing permissions and limitations under
+    the License.
+*/
+
+#include "tsutil/ts_errata.h"
+
+namespace ts
+{
+std::string
+err_category::message(int code) const
+{
+  std::string s;
+  swoc::bwprint(s, "{}", swoc::bwf::Errno(code));
+  return s;
+}
+} // namespace ts
diff --git a/tests/gold_tests/jsonrpc/plugins/jsonrpc_plugin_handler_test.cc b/tests/gold_tests/jsonrpc/plugins/jsonrpc_plugin_handler_test.cc
index 41d94bbe53..9bf7fe937f 100644
--- a/tests/gold_tests/jsonrpc/plugins/jsonrpc_plugin_handler_test.cc
+++ b/tests/gold_tests/jsonrpc/plugins/jsonrpc_plugin_handler_test.cc
@@ -27,9 +27,9 @@
 #include <fstream>
 
 #include "swoc/swoc_file.h"
+#include "tsutil/ts_bw_format.h"
 
 #include "yaml-cpp/yaml.h"
-#include "tscore/Errata.h"
 #include "tscore/Layout.h"
 #include "tsutil/ts_bw_format.h"
 #include "mgmt/rpc/jsonrpc/JsonRPC.h"