diff --git a/satrs-example/src/pus/action.rs b/satrs-example/src/pus/action.rs
index f5b779f..66c2918 100644
--- a/satrs-example/src/pus/action.rs
+++ b/satrs-example/src/pus/action.rs
@@ -1,7 +1,10 @@
 use log::{error, warn};
 use satrs::action::{ActionRequest, ActionRequestVariant};
 use satrs::pool::{SharedStaticMemoryPool, StoreAddr};
-use satrs::pus::action::PusService8ActionRequestHandler;
+use satrs::pus::action::{
+    ActionReplyPusWithActionId, ActiveActionRequest, DefaultActiveActionRequestMap,
+    PusService8ActionRequestHandler, PusService8ReplyHandler,
+};
 use satrs::pus::verification::{
     FailParams, TcStateAccepted, VerificationReporterWithSharedPoolMpscBoundedSender,
     VerificationReporterWithVecMpscSender, VerificationReportingProvider, VerificationToken,
@@ -9,8 +12,9 @@ use satrs::pus::verification::{
 use satrs::pus::{
     EcssTcAndToken, EcssTcInMemConverter, EcssTcInSharedStoreConverter, EcssTcInVecConverter,
     EcssTcReceiverCore, EcssTmSenderCore, MpscTcReceiver, PusPacketHandlerResult,
-    PusPacketHandlingError, PusServiceHelper, PusTcToRequestConverter, TmAsVecSenderWithId,
-    TmAsVecSenderWithMpsc, TmInSharedPoolSenderWithBoundedMpsc, TmInSharedPoolSenderWithId,
+    PusPacketHandlingError, PusServiceHelper, PusTcToRequestConverter, ReplyHandlerHook,
+    TmAsVecSenderWithId, TmAsVecSenderWithMpsc, TmInSharedPoolSenderWithBoundedMpsc,
+    TmInSharedPoolSenderWithId,
 };
 use satrs::request::TargetAndApidId;
 use satrs::spacepackets::ecss::tc::PusTcReader;
@@ -22,8 +26,6 @@ use std::sync::mpsc::{self};
 
 use crate::requests::GenericRequestRouter;
 
-use super::GenericRoutingErrorHandler;
-
 #[derive(Default)]
 pub struct ExampleActionRequestConverter {}
 
@@ -97,19 +99,29 @@ pub fn create_action_service_static(
         "PUS_8_TC_RECV",
         pus_action_rx,
     );
-    let pus_8_handler = PusService8ActionRequestHandler::new(
+    let action_request_handler = PusService8ActionRequestHandler::new(
         PusServiceHelper::new(
             action_srv_receiver,
-            action_srv_tm_sender,
+            action_srv_tm_sender.clone(),
             PUS_APID,
             verif_reporter.clone(),
             EcssTcInSharedStoreConverter::new(tc_pool.clone(), 2048),
         ),
         ExampleActionRequestConverter::default(),
         action_router,
-        GenericRoutingErrorHandler::<8>::default(),
     );
-    Pus8Wrapper { pus_8_handler }
+    let action_reply_handler = PusService8ReplyHandler::new_from_now(
+        verif_reporter.clone(),
+        DefaultActiveActionRequestMap::default(),
+        1024,
+        PusActionReplyHook::default(),
+        action_srv_tm_sender,
+    )
+    .expect("Failed to create PUS 8 reply handler");
+    Pus8Wrapper {
+        action_request_handler,
+        action_reply_handler,
+    }
 }
 
 pub fn create_action_service_dynamic(
@@ -133,35 +145,69 @@ pub fn create_action_service_dynamic(
         "PUS_8_TC_RECV",
         pus_action_rx,
     );
-    let pus_8_handler = PusService8ActionRequestHandler::new(
+    let action_request_handler = PusService8ActionRequestHandler::new(
         PusServiceHelper::new(
             action_srv_receiver,
-            action_srv_tm_sender,
+            action_srv_tm_sender.clone(),
             PUS_APID,
             verif_reporter.clone(),
             EcssTcInVecConverter::default(),
         ),
         ExampleActionRequestConverter::default(),
         action_router,
-        GenericRoutingErrorHandler::<8>::default(),
     );
-    Pus8Wrapper { pus_8_handler }
+    let action_reply_handler = PusService8ReplyHandler::new_from_now(
+        verif_reporter.clone(),
+        DefaultActiveActionRequestMap::default(),
+        1024,
+        PusActionReplyHook::default(),
+        action_srv_tm_sender,
+    )
+    .expect("Failed to create PUS 8 reply handler");
+    Pus8Wrapper {
+        action_request_handler,
+        action_reply_handler,
+    }
 }
 
+#[derive(Default)]
+pub struct PusActionReplyHook {}
+
+impl ReplyHandlerHook<ActiveActionRequest, ActionReplyPusWithActionId> for PusActionReplyHook {
+    fn handle_unexpected_reply(
+        &mut self,
+        reply: &satrs::request::GenericMessage<ActionReplyPusWithActionId>,
+    ) {
+        println!("received unexpected action reply {:?}", reply);
+    }
+
+    fn timeout_callback(&self, active_request: &ActiveActionRequest) {
+        println!("active request {active_request:?} timed out");
+    }
+
+    fn timeout_error_code(&self) -> satrs::res_code::ResultU16 {
+        todo!()
+    }
+}
 pub struct Pus8Wrapper<
     TcReceiver: EcssTcReceiverCore,
     TmSender: EcssTmSenderCore,
     TcInMemConverter: EcssTcInMemConverter,
     VerificationReporter: VerificationReportingProvider,
 > {
-    pub(crate) pus_8_handler: PusService8ActionRequestHandler<
+    pub(crate) action_request_handler: PusService8ActionRequestHandler<
         TcReceiver,
         TmSender,
         TcInMemConverter,
         VerificationReporter,
         ExampleActionRequestConverter,
         GenericRequestRouter,
-        GenericRoutingErrorHandler<8>,
+    >,
+    pub(crate) action_reply_handler: PusService8ReplyHandler<
+        VerificationReporter,
+        DefaultActiveActionRequestMap,
+        PusActionReplyHook,
+        TmSender,
     >,
 }
 
@@ -173,7 +219,7 @@ impl<
     > Pus8Wrapper<TcReceiver, TmSender, TcInMemConverter, VerificationReporter>
 {
     pub fn handle_next_packet(&mut self) -> bool {
-        match self.pus_8_handler.handle_one_tc() {
+        match self.action_request_handler.handle_one_tc() {
             Ok(result) => match result {
                 PusPacketHandlerResult::RequestHandled => {}
                 PusPacketHandlerResult::RequestHandledPartialSuccess(e) => {
@@ -193,6 +239,7 @@ impl<
                 error!("PUS packet handling error: {error:?}")
             }
         }
+        // self.action_reply_handler.handle_replies();
         false
     }
 }
diff --git a/satrs-example/src/pus/hk.rs b/satrs-example/src/pus/hk.rs
index 48a54be..8f6d608 100644
--- a/satrs-example/src/pus/hk.rs
+++ b/satrs-example/src/pus/hk.rs
@@ -1,18 +1,16 @@
 use log::{error, warn};
 use satrs::hk::{CollectionIntervalFactor, HkRequest};
 use satrs::pool::{SharedStaticMemoryPool, StoreAddr};
-use satrs::pus::hk::{PusHkToRequestConverter, PusService3HkHandler};
-use satrs::pus::verification::std_mod::{
-    VerificationReporterWithSharedPoolMpscBoundedSender, VerificationReporterWithVecMpscSender,
-};
+use satrs::pus::hk::PusService3HkRequestHandler;
 use satrs::pus::verification::{
-    FailParams, TcStateAccepted, VerificationReportingProvider, VerificationToken,
+    FailParams, TcStateAccepted, VerificationReporterWithSharedPoolMpscBoundedSender,
+    VerificationReporterWithVecMpscSender, VerificationReportingProvider, VerificationToken,
 };
 use satrs::pus::{
     EcssTcAndToken, EcssTcInMemConverter, EcssTcInSharedStoreConverter, EcssTcInVecConverter,
     EcssTcReceiverCore, EcssTmSenderCore, MpscTcReceiver, PusPacketHandlerResult,
-    PusPacketHandlingError, PusServiceHelper, TmAsVecSenderWithId, TmAsVecSenderWithMpsc,
-    TmInSharedPoolSenderWithBoundedMpsc, TmInSharedPoolSenderWithId,
+    PusPacketHandlingError, PusServiceHelper, PusTcToRequestConverter, TmAsVecSenderWithId,
+    TmAsVecSenderWithMpsc, TmInSharedPoolSenderWithBoundedMpsc, TmInSharedPoolSenderWithId,
 };
 use satrs::request::TargetAndApidId;
 use satrs::spacepackets::ecss::tc::PusTcReader;
@@ -24,12 +22,10 @@ use std::sync::mpsc::{self};
 
 use crate::requests::GenericRequestRouter;
 
-use super::GenericRoutingErrorHandler;
-
 #[derive(Default)]
 pub struct ExampleHkRequestConverter {}
 
-impl PusHkToRequestConverter for ExampleHkRequestConverter {
+impl PusTcToRequestConverter<HkRequest> for ExampleHkRequestConverter {
     type Error = PusPacketHandlingError;
 
     fn convert(
@@ -165,7 +161,7 @@ pub fn create_hk_service_static(
     );
     let hk_srv_receiver =
         MpscTcReceiver::new(TcReceiverId::PusHk as ChannelId, "PUS_8_TC_RECV", pus_hk_rx);
-    let pus_3_handler = PusService3HkHandler::new(
+    let pus_3_handler = PusService3HkRequestHandler::new(
         PusServiceHelper::new(
             hk_srv_receiver,
             hk_srv_tm_sender,
@@ -175,7 +171,6 @@ pub fn create_hk_service_static(
         ),
         ExampleHkRequestConverter::default(),
         request_router,
-        GenericRoutingErrorHandler::default(),
     );
     Pus3Wrapper { pus_3_handler }
 }
@@ -198,7 +193,7 @@ pub fn create_hk_service_dynamic(
     );
     let hk_srv_receiver =
         MpscTcReceiver::new(TcReceiverId::PusHk as ChannelId, "PUS_8_TC_RECV", pus_hk_rx);
-    let pus_3_handler = PusService3HkHandler::new(
+    let pus_3_handler = PusService3HkRequestHandler::new(
         PusServiceHelper::new(
             hk_srv_receiver,
             hk_srv_tm_sender,
@@ -208,7 +203,6 @@ pub fn create_hk_service_dynamic(
         ),
         ExampleHkRequestConverter::default(),
         request_router,
-        GenericRoutingErrorHandler::default(),
     );
     Pus3Wrapper { pus_3_handler }
 }
@@ -219,14 +213,13 @@ pub struct Pus3Wrapper<
     TcInMemConverter: EcssTcInMemConverter,
     VerificationReporter: VerificationReportingProvider,
 > {
-    pub(crate) pus_3_handler: PusService3HkHandler<
+    pub(crate) pus_3_handler: PusService3HkRequestHandler<
         TcReceiver,
         TmSender,
         TcInMemConverter,
         VerificationReporter,
         ExampleHkRequestConverter,
         GenericRequestRouter,
-        GenericRoutingErrorHandler<3>,
     >,
 }
 
diff --git a/satrs-example/src/pus/mod.rs b/satrs-example/src/pus/mod.rs
index 2b6c3ed..60a4644 100644
--- a/satrs-example/src/pus/mod.rs
+++ b/satrs-example/src/pus/mod.rs
@@ -1,9 +1,7 @@
 use crate::tmtc::MpscStoreAndSendError;
 use log::warn;
 use satrs::pus::verification::{FailParams, VerificationReportingProvider};
-use satrs::pus::{
-    EcssTcAndToken, GenericRoutingError, PusPacketHandlerResult, PusRoutingErrorHandler, TcInMemory,
-};
+use satrs::pus::{EcssTcAndToken, PusPacketHandlerResult, TcInMemory};
 use satrs::spacepackets::ecss::tc::PusTcReader;
 use satrs::spacepackets::ecss::PusServiceId;
 use satrs::spacepackets::time::cds::TimeProvider;
@@ -153,56 +151,3 @@ impl<VerificationReporter: VerificationReportingProvider> PusReceiver<Verificati
         Ok(PusPacketHandlerResult::RequestHandled)
     }
 }
-
-#[derive(Default)]
-pub struct GenericRoutingErrorHandler<const SERVICE_ID: u8> {}
-
-impl<const SERVICE_ID: u8> PusRoutingErrorHandler for GenericRoutingErrorHandler<SERVICE_ID> {
-    type Error = satrs::pus::GenericRoutingError;
-
-    fn handle_error(
-        &self,
-        target_id: satrs::TargetId,
-        token: satrs::pus::verification::VerificationToken<
-            satrs::pus::verification::TcStateAccepted,
-        >,
-        _tc: &PusTcReader,
-        error: Self::Error,
-        time_stamp: &[u8],
-        verif_reporter: &impl VerificationReportingProvider,
-    ) {
-        warn!("Routing request for service {SERVICE_ID} failed: {error:?}");
-        match error {
-            GenericRoutingError::UnknownTargetId(id) => {
-                let mut fail_data: [u8; 8] = [0; 8];
-                fail_data.copy_from_slice(&id.to_be_bytes());
-                verif_reporter
-                    .start_failure(
-                        token,
-                        FailParams::new(time_stamp, &tmtc_err::UNKNOWN_TARGET_ID, &fail_data),
-                    )
-                    .expect("Sending start failure failed");
-            }
-            GenericRoutingError::SendError(_) => {
-                let mut fail_data: [u8; 8] = [0; 8];
-                fail_data.copy_from_slice(&target_id.to_be_bytes());
-                verif_reporter
-                    .start_failure(
-                        token,
-                        FailParams::new(time_stamp, &tmtc_err::ROUTING_ERROR, &fail_data),
-                    )
-                    .expect("Sending start failure failed");
-            }
-            GenericRoutingError::NotEnoughAppData { expected, found } => {
-                let mut context_info = (found as u32).to_be_bytes().to_vec();
-                context_info.extend_from_slice(&(expected as u32).to_be_bytes());
-                verif_reporter
-                    .start_failure(
-                        token,
-                        FailParams::new(time_stamp, &tmtc_err::NOT_ENOUGH_APP_DATA, &context_info),
-                    )
-                    .expect("Sending start failure failed");
-            }
-        }
-    }
-}
diff --git a/satrs-example/src/requests.rs b/satrs-example/src/requests.rs
index 0c27b9e..6747a33 100644
--- a/satrs-example/src/requests.rs
+++ b/satrs-example/src/requests.rs
@@ -2,14 +2,19 @@ use std::collections::HashMap;
 use std::sync::mpsc;
 
 use derive_new::new;
+use log::warn;
 use satrs::action::ActionRequest;
 use satrs::hk::HkRequest;
 use satrs::mode::ModeRequest;
-use satrs::pus::hk::PusHkRequestRouter;
-use satrs::pus::verification::{TcStateAccepted, VerificationToken};
+use satrs::pus::verification::{
+    FailParams, TcStateAccepted, VerificationReportingProvider, VerificationToken,
+};
 use satrs::pus::{GenericRoutingError, PusRequestRouter};
 use satrs::queue::GenericSendError;
+use satrs::spacepackets::ecss::tc::PusTcReader;
+use satrs::spacepackets::ecss::PusPacket;
 use satrs::TargetId;
+use satrs_example::config::tmtc_err;
 
 #[allow(dead_code)]
 #[derive(Clone, Eq, PartialEq, Debug)]
@@ -48,7 +53,57 @@ impl RequestWithToken {
 #[derive(Default, Clone)]
 pub struct GenericRequestRouter(pub HashMap<TargetId, mpsc::Sender<RequestWithToken>>);
 
-impl PusHkRequestRouter for GenericRequestRouter {
+impl GenericRequestRouter {
+    fn handle_error_generic(
+        &self,
+        target_id: satrs::TargetId,
+        token: satrs::pus::verification::VerificationToken<
+            satrs::pus::verification::TcStateAccepted,
+        >,
+        tc: &PusTcReader,
+        error: GenericRoutingError,
+        time_stamp: &[u8],
+        verif_reporter: &impl VerificationReportingProvider,
+    ) {
+        warn!(
+            "Routing request for service {} failed: {error:?}",
+            tc.service()
+        );
+        match error {
+            GenericRoutingError::UnknownTargetId(id) => {
+                let mut fail_data: [u8; 8] = [0; 8];
+                fail_data.copy_from_slice(&id.to_be_bytes());
+                verif_reporter
+                    .start_failure(
+                        token,
+                        FailParams::new(time_stamp, &tmtc_err::UNKNOWN_TARGET_ID, &fail_data),
+                    )
+                    .expect("Sending start failure failed");
+            }
+            GenericRoutingError::SendError(_) => {
+                let mut fail_data: [u8; 8] = [0; 8];
+                fail_data.copy_from_slice(&target_id.to_be_bytes());
+                verif_reporter
+                    .start_failure(
+                        token,
+                        FailParams::new(time_stamp, &tmtc_err::ROUTING_ERROR, &fail_data),
+                    )
+                    .expect("Sending start failure failed");
+            }
+            GenericRoutingError::NotEnoughAppData { expected, found } => {
+                let mut context_info = (found as u32).to_be_bytes().to_vec();
+                context_info.extend_from_slice(&(expected as u32).to_be_bytes());
+                verif_reporter
+                    .start_failure(
+                        token,
+                        FailParams::new(time_stamp, &tmtc_err::NOT_ENOUGH_APP_DATA, &context_info),
+                    )
+                    .expect("Sending start failure failed");
+            }
+        }
+    }
+}
+impl PusRequestRouter<HkRequest> for GenericRequestRouter {
     type Error = GenericRoutingError;
 
     fn route(
@@ -68,6 +123,19 @@ impl PusHkRequestRouter for GenericRequestRouter {
         }
         Ok(())
     }
+    fn handle_error(
+        &self,
+        target_id: satrs::TargetId,
+        token: satrs::pus::verification::VerificationToken<
+            satrs::pus::verification::TcStateAccepted,
+        >,
+        tc: &PusTcReader,
+        error: GenericRoutingError,
+        time_stamp: &[u8],
+        verif_reporter: &impl VerificationReportingProvider,
+    ) {
+        self.handle_error_generic(target_id, token, tc, error, time_stamp, verif_reporter)
+    }
 }
 
 impl PusRequestRouter<ActionRequest> for GenericRequestRouter {
@@ -90,4 +158,17 @@ impl PusRequestRouter<ActionRequest> for GenericRequestRouter {
         }
         Ok(())
     }
+    fn handle_error(
+        &self,
+        target_id: satrs::TargetId,
+        token: satrs::pus::verification::VerificationToken<
+            satrs::pus::verification::TcStateAccepted,
+        >,
+        tc: &PusTcReader,
+        error: GenericRoutingError,
+        time_stamp: &[u8],
+        verif_reporter: &impl VerificationReportingProvider,
+    ) {
+        self.handle_error_generic(target_id, token, tc, error, time_stamp, verif_reporter)
+    }
 }
diff --git a/satrs/src/mode.rs b/satrs/src/mode.rs
index 3a099ce..5c83788 100644
--- a/satrs/src/mode.rs
+++ b/satrs/src/mode.rs
@@ -1,4 +1,5 @@
 use core::mem::size_of;
+use satrs_shared::res_code::ResultU16;
 #[cfg(feature = "serde")]
 use serde::{Deserialize, Serialize};
 use spacepackets::ByteConversionError;
@@ -53,7 +54,7 @@ impl ModeAndSubmode {
         })
     }
 
-    pub fn to_be_bytes(&self, buf: &mut [u8]) -> Result<usize, ByteConversionError> {
+    pub fn write_to_be_bytes(&self, buf: &mut [u8]) -> Result<usize, ByteConversionError> {
         if buf.len() < Self::RAW_LEN {
             return Err(ByteConversionError::ToSliceTooSmall {
                 expected: Self::RAW_LEN,
@@ -114,6 +115,13 @@ pub enum ModeRequest {
     AnnounceModeRecursive,
 }
 
+#[derive(Debug, Copy, Clone, PartialEq, Eq)]
+#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
+pub struct TargetedModeRequest {
+    target_id: TargetId,
+    mode_request: ModeRequest,
+}
+
 #[derive(Debug, Copy, Clone, PartialEq, Eq)]
 #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
 pub enum ModeReply {
@@ -121,20 +129,15 @@ pub enum ModeReply {
     ModeInfo(ModeAndSubmode),
     /// Reply to a mode request to confirm the commanded mode was reached.
     ModeReply(ModeAndSubmode),
-    // Can not reach the commanded mode. Returns the mode which was reached in the end.
-    CantReachMode(ModeAndSubmode),
+    // Can not reach the commanded mode. Contains a reason as a [ResultU16].
+    CantReachMode(ResultU16),
     WrongMode {
         expected: ModeAndSubmode,
         reached: ModeAndSubmode,
     },
 }
 
-#[derive(Debug, Copy, Clone, PartialEq, Eq)]
-#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
-pub struct TargetedModeRequest {
-    target_id: TargetId,
-    mode_request: ModeRequest,
-}
+pub type GenericModeReply = GenericMessage<ModeReply>;
 
 pub trait ModeRequestSender {
     fn local_channel_id(&self) -> ChannelId;
@@ -146,37 +149,12 @@ pub trait ModeRequestSender {
     ) -> Result<(), GenericTargetedMessagingError>;
 }
 
-pub trait ModeReplySender {
-    fn local_channel_id(&self) -> ChannelId;
-
-    fn send_mode_reply(
-        &self,
-        request_id: RequestId,
-        target_id: ChannelId,
-        reply: ModeReply,
-    ) -> Result<(), GenericTargetedMessagingError>;
-}
-
 pub trait ModeRequestReceiver {
     fn try_recv_mode_request(
         &self,
     ) -> Result<Option<GenericMessage<ModeRequest>>, GenericTargetedMessagingError>;
 }
 
-pub trait ModeReplyReceiver {
-    fn try_recv_mode_reply(
-        &self,
-    ) -> Result<Option<GenericMessage<ModeReply>>, GenericTargetedMessagingError>;
-}
-
-impl<R: MessageReceiver<ModeReply>> ModeReplyReceiver for MessageReceiverWithId<ModeReply, R> {
-    fn try_recv_mode_reply(
-        &self,
-    ) -> Result<Option<GenericMessage<ModeReply>>, GenericTargetedMessagingError> {
-        self.try_recv_message()
-    }
-}
-
 impl<R: MessageReceiver<ModeRequest>> ModeRequestReceiver
     for MessageReceiverWithId<ModeRequest, R>
 {
@@ -214,32 +192,46 @@ pub trait ModeRequestHandler: ModeProvider {
     fn handle_mode_reached(&mut self) -> Result<(), GenericTargetedMessagingError>;
 }
 
+pub trait ModeReplyReceiver {
+    fn try_recv_mode_reply(
+        &self,
+    ) -> Result<Option<GenericMessage<ModeReply>>, GenericTargetedMessagingError>;
+}
+
+impl<R: MessageReceiver<ModeReply>> ModeReplyReceiver for MessageReceiverWithId<ModeReply, R> {
+    fn try_recv_mode_reply(
+        &self,
+    ) -> Result<Option<GenericMessage<ModeReply>>, GenericTargetedMessagingError> {
+        self.try_recv_message()
+    }
+}
+
+pub trait ModeReplySender {
+    fn local_channel_id(&self) -> ChannelId;
+
+    fn send_mode_reply(
+        &self,
+        request_id: RequestId,
+        target_id: ChannelId,
+        reply: ModeReply,
+    ) -> Result<(), GenericTargetedMessagingError>;
+}
+
 #[cfg(feature = "alloc")]
 #[cfg_attr(doc_cfg, doc(cfg(feature = "alloc")))]
 pub mod alloc_mod {
-    use crate::request::{
-        MessageSender, MessageSenderAndReceiver, MessageSenderMap, MessageSenderMapWithId,
-        RequestAndReplySenderAndReceiver,
+    use crate::{
+        mode::ModeRequest,
+        queue::GenericTargetedMessagingError,
+        request::{
+            MessageSender, MessageSenderAndReceiver, MessageSenderMap, MessageSenderMapWithId,
+            RequestAndReplySenderAndReceiver, RequestId,
+        },
+        ChannelId,
     };
 
     use super::*;
 
-    impl<S: MessageSender<ModeRequest>> MessageSenderMap<ModeRequest, S> {
-        pub fn send_mode_request(
-            &self,
-            request_id: RequestId,
-            local_id: ChannelId,
-            target_id: ChannelId,
-            request: ModeRequest,
-        ) -> Result<(), GenericTargetedMessagingError> {
-            self.send_message(request_id, local_id, target_id, request)
-        }
-
-        pub fn add_request_target(&mut self, target_id: ChannelId, request_sender: S) {
-            self.add_message_target(target_id, request_sender)
-        }
-    }
-
     impl<S: MessageSender<ModeReply>> MessageSenderMap<ModeReply, S> {
         pub fn send_mode_reply(
             &self,
@@ -271,21 +263,6 @@ pub mod alloc_mod {
         }
     }
 
-    impl<S: MessageSender<ModeRequest>> ModeRequestSender for MessageSenderMapWithId<ModeRequest, S> {
-        fn local_channel_id(&self) -> ChannelId {
-            self.local_channel_id
-        }
-
-        fn send_mode_request(
-            &self,
-            request_id: RequestId,
-            target_id: ChannelId,
-            request: ModeRequest,
-        ) -> Result<(), GenericTargetedMessagingError> {
-            self.send_message(request_id, target_id, request)
-        }
-    }
-
     impl<FROM, S: MessageSender<ModeReply>, R: MessageReceiver<FROM>> ModeReplySender
         for MessageSenderAndReceiver<ModeReply, FROM, S, R>
     {
@@ -317,51 +294,6 @@ pub mod alloc_mod {
             self.message_receiver.try_recv_message()
         }
     }
-    impl<TO, S: MessageSender<TO>, R: MessageReceiver<ModeRequest>> ModeRequestReceiver
-        for MessageSenderAndReceiver<TO, ModeRequest, S, R>
-    {
-        fn try_recv_mode_request(
-            &self,
-        ) -> Result<Option<GenericMessage<ModeRequest>>, GenericTargetedMessagingError> {
-            self.message_receiver.try_recv_message()
-        }
-    }
-
-    impl<FROM, S: MessageSender<ModeRequest>, R: MessageReceiver<FROM>> ModeRequestSender
-        for MessageSenderAndReceiver<ModeRequest, FROM, S, R>
-    {
-        fn local_channel_id(&self) -> ChannelId {
-            self.local_channel_id_generic()
-        }
-
-        fn send_mode_request(
-            &self,
-            request_id: RequestId,
-            target_id: ChannelId,
-            request: ModeRequest,
-        ) -> Result<(), GenericTargetedMessagingError> {
-            self.message_sender_map.send_mode_request(
-                request_id,
-                self.local_channel_id(),
-                target_id,
-                request,
-            )
-        }
-    }
-
-    impl<
-            REPLY,
-            S0: MessageSender<ModeRequest>,
-            R0: MessageReceiver<REPLY>,
-            S1: MessageSender<REPLY>,
-            R1: MessageReceiver<ModeRequest>,
-        > RequestAndReplySenderAndReceiver<ModeRequest, REPLY, S0, R0, S1, R1>
-    {
-        pub fn add_request_target(&mut self, target_id: ChannelId, request_sender: S0) {
-            self.request_sender_map
-                .add_message_target(target_id, request_sender)
-        }
-    }
 
     impl<
             REQUEST,
@@ -377,34 +309,6 @@ pub mod alloc_mod {
         }
     }
 
-    impl<
-            REPLY,
-            S0: MessageSender<ModeRequest>,
-            R0: MessageReceiver<REPLY>,
-            S1: MessageSender<REPLY>,
-            R1: MessageReceiver<ModeRequest>,
-        > ModeRequestSender
-        for RequestAndReplySenderAndReceiver<ModeRequest, REPLY, S0, R0, S1, R1>
-    {
-        fn local_channel_id(&self) -> ChannelId {
-            self.local_channel_id_generic()
-        }
-
-        fn send_mode_request(
-            &self,
-            request_id: RequestId,
-            target_id: ChannelId,
-            request: ModeRequest,
-        ) -> Result<(), GenericTargetedMessagingError> {
-            self.request_sender_map.send_mode_request(
-                request_id,
-                self.local_channel_id(),
-                target_id,
-                request,
-            )
-        }
-    }
-
     impl<
             REQUEST,
             S0: MessageSender<REQUEST>,
@@ -448,22 +352,6 @@ pub mod alloc_mod {
         }
     }
 
-    impl<
-            REPLY,
-            S0: MessageSender<ModeRequest>,
-            R0: MessageReceiver<REPLY>,
-            S1: MessageSender<REPLY>,
-            R1: MessageReceiver<ModeRequest>,
-        > ModeRequestReceiver
-        for RequestAndReplySenderAndReceiver<ModeRequest, REPLY, S0, R0, S1, R1>
-    {
-        fn try_recv_mode_request(
-            &self,
-        ) -> Result<Option<GenericMessage<ModeRequest>>, GenericTargetedMessagingError> {
-            self.request_receiver.try_recv_message()
-        }
-    }
-
     /// Helper type definition for a mode handler which can handle mode requests.
     pub type ModeRequestHandlerInterface<S, R> =
         MessageSenderAndReceiver<ModeReply, ModeRequest, S, R>;
@@ -511,6 +399,127 @@ pub mod alloc_mod {
     /// process mode requests.
     pub type ModeInterface<S0, R0, S1, R1> =
         RequestAndReplySenderAndReceiver<ModeRequest, ModeReply, S0, R0, S1, R1>;
+
+    impl<S: MessageSender<ModeRequest>> MessageSenderMap<ModeRequest, S> {
+        pub fn send_mode_request(
+            &self,
+            request_id: RequestId,
+            local_id: ChannelId,
+            target_id: ChannelId,
+            request: ModeRequest,
+        ) -> Result<(), GenericTargetedMessagingError> {
+            self.send_message(request_id, local_id, target_id, request)
+        }
+
+        pub fn add_request_target(&mut self, target_id: ChannelId, request_sender: S) {
+            self.add_message_target(target_id, request_sender)
+        }
+    }
+
+    impl<S: MessageSender<ModeRequest>> ModeRequestSender for MessageSenderMapWithId<ModeRequest, S> {
+        fn local_channel_id(&self) -> ChannelId {
+            self.local_channel_id
+        }
+
+        fn send_mode_request(
+            &self,
+            request_id: RequestId,
+            target_id: ChannelId,
+            request: ModeRequest,
+        ) -> Result<(), GenericTargetedMessagingError> {
+            self.send_message(request_id, target_id, request)
+        }
+    }
+
+    impl<TO, S: MessageSender<TO>, R: MessageReceiver<ModeRequest>> ModeRequestReceiver
+        for MessageSenderAndReceiver<TO, ModeRequest, S, R>
+    {
+        fn try_recv_mode_request(
+            &self,
+        ) -> Result<Option<GenericMessage<ModeRequest>>, GenericTargetedMessagingError> {
+            self.message_receiver.try_recv_message()
+        }
+    }
+
+    impl<FROM, S: MessageSender<ModeRequest>, R: MessageReceiver<FROM>> ModeRequestSender
+        for MessageSenderAndReceiver<ModeRequest, FROM, S, R>
+    {
+        fn local_channel_id(&self) -> ChannelId {
+            self.local_channel_id_generic()
+        }
+
+        fn send_mode_request(
+            &self,
+            request_id: RequestId,
+            target_id: ChannelId,
+            request: ModeRequest,
+        ) -> Result<(), GenericTargetedMessagingError> {
+            self.message_sender_map.send_mode_request(
+                request_id,
+                self.local_channel_id(),
+                target_id,
+                request,
+            )
+        }
+    }
+
+    impl<
+            REPLY,
+            S0: MessageSender<ModeRequest>,
+            R0: MessageReceiver<REPLY>,
+            S1: MessageSender<REPLY>,
+            R1: MessageReceiver<ModeRequest>,
+        > RequestAndReplySenderAndReceiver<ModeRequest, REPLY, S0, R0, S1, R1>
+    {
+        pub fn add_request_target(&mut self, target_id: ChannelId, request_sender: S0) {
+            self.request_sender_map
+                .add_message_target(target_id, request_sender)
+        }
+    }
+
+    impl<
+            REPLY,
+            S0: MessageSender<ModeRequest>,
+            R0: MessageReceiver<REPLY>,
+            S1: MessageSender<REPLY>,
+            R1: MessageReceiver<ModeRequest>,
+        > ModeRequestSender
+        for RequestAndReplySenderAndReceiver<ModeRequest, REPLY, S0, R0, S1, R1>
+    {
+        fn local_channel_id(&self) -> ChannelId {
+            self.local_channel_id_generic()
+        }
+
+        fn send_mode_request(
+            &self,
+            request_id: RequestId,
+            target_id: ChannelId,
+            request: ModeRequest,
+        ) -> Result<(), GenericTargetedMessagingError> {
+            self.request_sender_map.send_mode_request(
+                request_id,
+                self.local_channel_id(),
+                target_id,
+                request,
+            )
+        }
+    }
+
+    impl<
+            REPLY,
+            S0: MessageSender<ModeRequest>,
+            R0: MessageReceiver<REPLY>,
+            S1: MessageSender<REPLY>,
+            R1: MessageReceiver<ModeRequest>,
+        > ModeRequestReceiver
+        for RequestAndReplySenderAndReceiver<ModeRequest, REPLY, S0, R0, S1, R1>
+    {
+        fn try_recv_mode_request(
+            &self,
+        ) -> Result<Option<GenericMessage<ModeRequest>>, GenericTargetedMessagingError> {
+            self.request_receiver.try_recv_message()
+        }
+    }
 }
 
 #[cfg(feature = "std")]
@@ -518,6 +527,8 @@ pub mod alloc_mod {
 pub mod std_mod {
     use std::sync::mpsc;
 
+    use crate::request::GenericMessage;
+
     use super::*;
 
     pub type ModeRequestHandlerMpsc = ModeRequestHandlerInterface<
@@ -553,115 +564,4 @@ pub mod std_mod {
 }
 
 #[cfg(test)]
-mod tests {
-    use std::sync::mpsc;
-
-    use crate::{
-        mode::{ModeAndSubmode, ModeReply, ModeReplySender, ModeRequestSender},
-        request::GenericMessage,
-    };
-
-    use super::{ModeRequest, ModeRequestorAndHandlerMpsc, ModeRequestorMpsc};
-
-    const TEST_CHANNEL_ID_0: u32 = 5;
-    const TEST_CHANNEL_ID_1: u32 = 6;
-    const TEST_CHANNEL_ID_2: u32 = 7;
-
-    #[test]
-    fn test_simple_mode_requestor() {
-        let (reply_sender, reply_receiver) = mpsc::channel();
-        let (request_sender, request_receiver) = mpsc::channel();
-        let mut mode_requestor = ModeRequestorMpsc::new(TEST_CHANNEL_ID_0, reply_receiver);
-        mode_requestor.add_message_target(TEST_CHANNEL_ID_1, request_sender);
-
-        // Send a request and verify it arrives at the receiver.
-        let request_id = 2;
-        let sent_request = ModeRequest::ReadMode;
-        mode_requestor
-            .send_mode_request(request_id, TEST_CHANNEL_ID_1, sent_request)
-            .expect("send failed");
-        let request = request_receiver.recv().expect("recv failed");
-        assert_eq!(request.request_id, 2);
-        assert_eq!(request.sender_id, TEST_CHANNEL_ID_0);
-        assert_eq!(request.message, sent_request);
-
-        // Send a reply and verify it arrives at the requestor.
-        let mode_reply = ModeReply::ModeReply(ModeAndSubmode::new(1, 5));
-        reply_sender
-            .send(GenericMessage::new(
-                request_id,
-                TEST_CHANNEL_ID_1,
-                mode_reply,
-            ))
-            .expect("send failed");
-        let reply = mode_requestor.try_recv_mode_reply().expect("recv failed");
-        assert!(reply.is_some());
-        let reply = reply.unwrap();
-        assert_eq!(reply.sender_id, TEST_CHANNEL_ID_1);
-        assert_eq!(reply.request_id, 2);
-        assert_eq!(reply.message, mode_reply);
-    }
-
-    #[test]
-    fn test_mode_requestor_and_request_handler_request_sending() {
-        let (_reply_sender_to_connector, reply_receiver_of_connector) = mpsc::channel();
-        let (_request_sender_to_connector, request_receiver_of_connector) = mpsc::channel();
-
-        let (request_sender_to_channel_1, request_receiver_channel_1) = mpsc::channel();
-        //let (reply_sender_to_channel_2, reply_receiver_channel_2) = mpsc::channel();
-        let mut mode_connector = ModeRequestorAndHandlerMpsc::new(
-            TEST_CHANNEL_ID_0,
-            request_receiver_of_connector,
-            reply_receiver_of_connector,
-        );
-        assert_eq!(
-            ModeRequestSender::local_channel_id(&mode_connector),
-            TEST_CHANNEL_ID_0
-        );
-        assert_eq!(
-            ModeReplySender::local_channel_id(&mode_connector),
-            TEST_CHANNEL_ID_0
-        );
-        assert_eq!(mode_connector.local_channel_id_generic(), TEST_CHANNEL_ID_0);
-
-        mode_connector.add_request_target(TEST_CHANNEL_ID_1, request_sender_to_channel_1);
-        //mode_connector.add_reply_target(TEST_CHANNEL_ID_2, reply_sender_to_channel_2);
-
-        // Send a request and verify it arrives at the receiver.
-        let request_id = 2;
-        let sent_request = ModeRequest::ReadMode;
-        mode_connector
-            .send_mode_request(request_id, TEST_CHANNEL_ID_1, sent_request)
-            .expect("send failed");
-
-        let request = request_receiver_channel_1.recv().expect("recv failed");
-        assert_eq!(request.request_id, 2);
-        assert_eq!(request.sender_id, TEST_CHANNEL_ID_0);
-        assert_eq!(request.message, ModeRequest::ReadMode);
-    }
-
-    #[test]
-    fn test_mode_requestor_and_request_handler_reply_sending() {
-        let (_reply_sender_to_connector, reply_receiver_of_connector) = mpsc::channel();
-        let (_request_sender_to_connector, request_receiver_of_connector) = mpsc::channel();
-
-        let (reply_sender_to_channel_2, reply_receiver_channel_2) = mpsc::channel();
-        let mut mode_connector = ModeRequestorAndHandlerMpsc::new(
-            TEST_CHANNEL_ID_0,
-            request_receiver_of_connector,
-            reply_receiver_of_connector,
-        );
-        mode_connector.add_reply_target(TEST_CHANNEL_ID_2, reply_sender_to_channel_2);
-
-        // Send a request and verify it arrives at the receiver.
-        let request_id = 2;
-        let sent_reply = ModeReply::ModeInfo(ModeAndSubmode::new(3, 5));
-        mode_connector
-            .send_mode_reply(request_id, TEST_CHANNEL_ID_2, sent_reply)
-            .expect("send failed");
-        let reply = reply_receiver_channel_2.recv().expect("recv failed");
-        assert_eq!(reply.request_id, 2);
-        assert_eq!(reply.sender_id, TEST_CHANNEL_ID_0);
-        assert_eq!(reply.message, sent_reply);
-    }
-}
+mod tests {}
diff --git a/satrs/src/pus/action.rs b/satrs/src/pus/action.rs
index 85d3dbd..881274c 100644
--- a/satrs/src/pus/action.rs
+++ b/satrs/src/pus/action.rs
@@ -122,7 +122,6 @@ pub mod std_mod {
         VerificationReporter,
         RequestConverter,
         RequestRouter,
-        RoutingErrorHandler,
         RoutingError = GenericRoutingError,
     > = PusTargetedRequestHandler<
         TcReceiver,
@@ -131,7 +130,6 @@ pub mod std_mod {
         VerificationReporter,
         RequestConverter,
         RequestRouter,
-        RoutingErrorHandler,
         ActionRequest,
         RoutingError,
     >;
@@ -326,7 +324,7 @@ mod tests {
         pus::{
             tests::{
                 PusServiceHandlerWithVecCommon, PusTestHarness, SimplePusPacketHandler,
-                TestConverter, TestRouter, TestRoutingErrorHandler, APP_DATA_TOO_SHORT, TEST_APID,
+                TestConverter, TestRouter, APP_DATA_TOO_SHORT, TEST_APID,
             },
             verification::{
                 self,
@@ -356,6 +354,20 @@ mod tests {
                 .push_back((target_id, request));
             self.check_for_injected_error()
         }
+
+        fn handle_error(
+            &self,
+            target_id: TargetId,
+            token: VerificationToken<TcStateAccepted>,
+            tc: &PusTcReader,
+            error: Self::Error,
+            time_stamp: &[u8],
+            verif_reporter: &impl VerificationReportingProvider,
+        ) {
+            self.routing_errors
+                .borrow_mut()
+                .push_back((target_id, error));
+        }
     }
 
     impl PusTcToRequestConverter<ActionRequest> for TestConverter<8> {
@@ -413,7 +425,6 @@ mod tests {
             TestVerificationReporter,
             TestConverter<8>,
             TestRouter<ActionRequest>,
-            TestRoutingErrorHandler,
         >,
     }
 
@@ -427,7 +438,6 @@ mod tests {
                     srv_handler,
                     TestConverter::default(),
                     TestRouter::default(),
-                    TestRoutingErrorHandler::default(),
                 ),
             }
         }
@@ -443,8 +453,8 @@ mod tests {
             }
         }
         delegate! {
-            to self.handler.routing_error_handler {
-                pub fn retrieve_next_error(&mut self) -> (TargetId, GenericRoutingError);
+            to self.handler.request_router {
+                pub fn retrieve_next_routing_error(&mut self) -> (TargetId, GenericRoutingError);
             }
         }
     }
@@ -714,7 +724,7 @@ mod tests {
             assert_eq!(data, &[]);
         }
 
-        let (target_id, found_error) = action_handler.retrieve_next_error();
+        let (target_id, found_error) = action_handler.retrieve_next_routing_error();
         assert_eq!(target_id, TEST_APID.into());
         check_error(found_error);
     }
diff --git a/satrs/src/pus/hk.rs b/satrs/src/pus/hk.rs
index 852e8f7..b44c3d2 100644
--- a/satrs/src/pus/hk.rs
+++ b/satrs/src/pus/hk.rs
@@ -6,6 +6,7 @@ pub use std_mod::*;
 
 #[cfg(feature = "alloc")]
 #[cfg_attr(doc_cfg, doc(cfg(feature = "alloc")))]
+#[allow(unused_imports)]
 pub use alloc_mod::*;
 
 use crate::{hk::HkRequest, TargetId};
@@ -26,158 +27,33 @@ pub trait PusHkRequestRouter {
 
 #[cfg(feature = "alloc")]
 #[cfg_attr(doc_cfg, doc(cfg(feature = "alloc")))]
-pub mod alloc_mod {
-    use spacepackets::ecss::tc::PusTcReader;
-
-    use crate::pus::verification::VerificationReportingProvider;
-
-    use super::*;
-
-    /// This trait is an abstraction for the conversion of a PUS service 8 action telecommand into
-    /// a [HkRequest].
-    ///
-    /// Having a dedicated trait for this allows maximum flexiblity and tailoring of the standard.
-    /// The only requirement is that a valid [TargetId] and a [HkRequest] are returned by the
-    /// core conversion function.
-    ///
-    /// The user should take care of performing the error handling as well. Some of the following
-    /// aspects might be relevant:
-    ///
-    /// - Checking the validity of the APID, service ID, subservice ID.
-    /// - Checking the validity of the user data.
-    ///
-    /// A [VerificationReportingProvider] is passed to the user to also allow handling
-    /// of the verification process as part of the PUS standard requirements.
-    pub trait PusHkToRequestConverter {
-        type Error;
-        fn convert(
-            &mut self,
-            token: VerificationToken<TcStateAccepted>,
-            tc: &PusTcReader,
-            time_stamp: &[u8],
-            verif_reporter: &impl VerificationReportingProvider,
-        ) -> Result<(TargetId, HkRequest), Self::Error>;
-    }
-}
+pub mod alloc_mod {}
 
 #[cfg(feature = "std")]
 #[cfg_attr(doc_cfg, doc(cfg(feature = "std")))]
 pub mod std_mod {
-    use crate::pus::{
-        get_current_cds_short_timestamp, verification::VerificationReportingProvider,
-        EcssTcInMemConverter, EcssTcReceiverCore, EcssTmSenderCore, GenericRoutingError,
-        PusPacketHandlerResult, PusPacketHandlingError, PusRoutingErrorHandler, PusServiceHelper,
-    };
+    use crate::pus::{GenericRoutingError, PusTargetedRequestHandler};
 
     use super::*;
 
-    /// This is a generic high-level handler for the PUS service 3 housekeeping service.
-    ///
-    /// It performs the following handling steps:
-    ///
-    /// 1. Retrieve the next TC packet from the [PusServiceHelper]. The [EcssTcInMemConverter]
-    ///    allows to configure the used telecommand memory backend.
-    /// 2. Convert the TC to a targeted action request using the provided
-    ///    [PusHkToRequestConverter]. The generic error type is constrained to the
-    ///    [PusPacketHandlerResult] for the concrete implementation which offers a packet handler.
-    /// 3. Route the action request using the provided [PusHkRequestRouter]. The generic error
-    ///    type is constrained to the [GenericRoutingError] for the concrete implementation.
-    /// 4. Handle all routing errors using the provided [PusRoutingErrorHandler]. The generic error
-    ///    type is constrained to the [GenericRoutingError] for the concrete implementation.
-    pub struct PusService3HkHandler<
-        TcReceiver: EcssTcReceiverCore,
-        TmSender: EcssTmSenderCore,
-        TcInMemConverter: EcssTcInMemConverter,
-        VerificationReporter: VerificationReportingProvider,
-        RequestConverter: PusHkToRequestConverter,
-        RequestRouter: PusHkRequestRouter<Error = RoutingError>,
-        RoutingErrorHandler: PusRoutingErrorHandler<Error = RoutingError>,
+    pub type PusService3HkRequestHandler<
+        TcReceiver,
+        TmSender,
+        TcInMemConverter,
+        VerificationReporter,
+        RequestConverter,
+        RequestRouter,
         RoutingError = GenericRoutingError,
-    > {
-        service_helper:
-            PusServiceHelper<TcReceiver, TmSender, TcInMemConverter, VerificationReporter>,
-        pub request_converter: RequestConverter,
-        pub request_router: RequestRouter,
-        pub routing_error_handler: RoutingErrorHandler,
-    }
-
-    impl<
-            TcReceiver: EcssTcReceiverCore,
-            TmSender: EcssTmSenderCore,
-            TcInMemConverter: EcssTcInMemConverter,
-            VerificationReporter: VerificationReportingProvider,
-            RequestConverter: PusHkToRequestConverter<Error = PusPacketHandlingError>,
-            RequestRouter: PusHkRequestRouter<Error = RoutingError>,
-            RoutingErrorHandler: PusRoutingErrorHandler<Error = RoutingError>,
-            RoutingError: Clone,
-        >
-        PusService3HkHandler<
-            TcReceiver,
-            TmSender,
-            TcInMemConverter,
-            VerificationReporter,
-            RequestConverter,
-            RequestRouter,
-            RoutingErrorHandler,
-            RoutingError,
-        >
-    where
-        PusPacketHandlingError: From<RoutingError>,
-    {
-        pub fn new(
-            service_helper: PusServiceHelper<
-                TcReceiver,
-                TmSender,
-                TcInMemConverter,
-                VerificationReporter,
-            >,
-            request_converter: RequestConverter,
-            request_router: RequestRouter,
-            routing_error_handler: RoutingErrorHandler,
-        ) -> Self {
-            Self {
-                service_helper,
-                request_converter,
-                request_router,
-                routing_error_handler,
-            }
-        }
-
-        pub fn handle_one_tc(&mut self) -> Result<PusPacketHandlerResult, PusPacketHandlingError> {
-            let possible_packet = self.service_helper.retrieve_and_accept_next_packet()?;
-            if possible_packet.is_none() {
-                return Ok(PusPacketHandlerResult::Empty);
-            }
-            let ecss_tc_and_token = possible_packet.unwrap();
-            let tc = self
-                .service_helper
-                .tc_in_mem_converter
-                .convert_ecss_tc_in_memory_to_reader(&ecss_tc_and_token.tc_in_memory)?;
-            let mut partial_error = None;
-            let time_stamp = get_current_cds_short_timestamp(&mut partial_error);
-            let (target_id, hk_request) = self.request_converter.convert(
-                ecss_tc_and_token.token,
-                &tc,
-                &time_stamp,
-                &self.service_helper.common.verification_handler,
-            )?;
-            if let Err(e) =
-                self.request_router
-                    .route(target_id, hk_request, ecss_tc_and_token.token)
-            {
-                self.routing_error_handler.handle_error(
-                    target_id,
-                    ecss_tc_and_token.token,
-                    &tc,
-                    e.clone(),
-                    &time_stamp,
-                    &self.service_helper.common.verification_handler,
-                );
-                return Err(e.into());
-            }
-            Ok(PusPacketHandlerResult::RequestHandled)
-        }
-    }
+    > = PusTargetedRequestHandler<
+        TcReceiver,
+        TmSender,
+        TcInMemConverter,
+        VerificationReporter,
+        RequestConverter,
+        RequestRouter,
+        HkRequest,
+        RoutingError,
+    >;
 }
 
 #[cfg(test)]
@@ -194,13 +70,13 @@ mod tests {
         CcsdsPacket, SequenceFlags, SpHeader,
     };
 
-    use crate::pus::{MpscTcReceiver, TmAsVecSenderWithMpsc};
+    use crate::pus::{MpscTcReceiver, PusTcToRequestConverter, TmAsVecSenderWithMpsc};
     use crate::{
         hk::HkRequest,
         pus::{
             tests::{
                 PusServiceHandlerWithVecCommon, PusTestHarness, SimplePusPacketHandler,
-                TestConverter, TestRouter, TestRoutingErrorHandler, APP_DATA_TOO_SHORT, TEST_APID,
+                TestConverter, TestRouter, APP_DATA_TOO_SHORT, TEST_APID,
             },
             verification::{
                 tests::TestVerificationReporter, FailParams, RequestId, TcStateAccepted,
@@ -212,7 +88,7 @@ mod tests {
         TargetId,
     };
 
-    use super::{PusHkRequestRouter, PusHkToRequestConverter, PusService3HkHandler};
+    use super::{PusHkRequestRouter, PusService3HkRequestHandler};
 
     impl PusHkRequestRouter for TestRouter<HkRequest> {
         type Error = GenericRoutingError;
@@ -230,7 +106,7 @@ mod tests {
         }
     }
 
-    impl PusHkToRequestConverter for TestConverter<3> {
+    impl PusTcToRequestConverter<HkRequest> for TestConverter<3> {
         type Error = PusPacketHandlingError;
         fn convert(
             &mut self,
@@ -277,14 +153,13 @@ mod tests {
 
     struct Pus3HandlerWithVecTester {
         common: PusServiceHandlerWithVecCommon<TestVerificationReporter>,
-        handler: PusService3HkHandler<
+        handler: PusService3HkRequestHandler<
             MpscTcReceiver,
             TmAsVecSenderWithMpsc,
             EcssTcInVecConverter,
             TestVerificationReporter,
             TestConverter<3>,
             TestRouter<HkRequest>,
-            TestRoutingErrorHandler,
         >,
     }
 
@@ -294,11 +169,10 @@ mod tests {
                 PusServiceHandlerWithVecCommon::new_with_test_verif_sender();
             Self {
                 common,
-                handler: PusService3HkHandler::new(
+                handler: PusService3HkRequestHandler::new(
                     srv_handler,
                     TestConverter::default(),
                     TestRouter::default(),
-                    TestRoutingErrorHandler::default(),
                 ),
             }
         }
@@ -314,8 +188,8 @@ mod tests {
             }
         }
         delegate! {
-            to self.handler.routing_error_handler {
-                pub fn retrieve_next_error(&mut self) -> (TargetId, GenericRoutingError);
+            to self.handler.request_router  {
+                pub fn retrieve_next_routing_error(&mut self) -> (TargetId, GenericRoutingError);
             }
         }
     }
@@ -399,7 +273,7 @@ mod tests {
             assert_eq!(unique_id, 1);
         }
 
-        let (target_id, found_error) = hk_handler.retrieve_next_error();
+        let (target_id, found_error) = hk_handler.retrieve_next_routing_error();
         assert_eq!(target_id, TEST_APID.into());
         check_error(found_error);
     }
diff --git a/satrs/src/pus/mod.rs b/satrs/src/pus/mod.rs
index 037dbce..5479951 100644
--- a/satrs/src/pus/mod.rs
+++ b/satrs/src/pus/mod.rs
@@ -44,7 +44,7 @@ pub use alloc_mod::*;
 #[cfg(feature = "std")]
 pub use std_mod::*;
 
-use self::verification::{FailParams, TcStateStarted};
+use self::verification::{FailParams, TcStateStarted, VerificationReportingProvider};
 
 #[derive(Debug, PartialEq, Eq, Clone)]
 pub enum PusTmWrapper<'tm> {
@@ -347,6 +347,15 @@ pub trait PusRequestRouter<Request> {
         hk_request: Request,
         token: VerificationToken<TcStateAccepted>,
     ) -> Result<(), Self::Error>;
+    fn handle_error(
+        &self,
+        target_id: TargetId,
+        token: VerificationToken<TcStateAccepted>,
+        tc: &PusTcReader,
+        error: Self::Error,
+        time_stamp: &[u8],
+        verif_reporter: &impl VerificationReportingProvider,
+    );
 }
 
 #[cfg(feature = "alloc")]
@@ -465,19 +474,6 @@ pub mod alloc_mod {
         ) -> Result<(TargetId, Request), Self::Error>;
     }
 
-    pub trait PusRoutingErrorHandler {
-        type Error;
-        fn handle_error(
-            &self,
-            target_id: TargetId,
-            token: VerificationToken<TcStateAccepted>,
-            tc: &PusTcReader,
-            error: Self::Error,
-            time_stamp: &[u8],
-            verif_reporter: &impl VerificationReportingProvider,
-        );
-    }
-
     #[derive(Clone, Debug)]
     pub struct DefaultActiveRequestMap<V>(pub HashMap<RequestId, V>);
 
@@ -704,10 +700,7 @@ pub mod std_mod {
     pub use cb_mod::*;
 
     use super::verification::VerificationReportingProvider;
-    use super::{
-        AcceptedEcssTcAndToken, PusRequestRouter, PusRoutingErrorHandler, PusTcToRequestConverter,
-        TcInMemory,
-    };
+    use super::{AcceptedEcssTcAndToken, PusRequestRouter, PusTcToRequestConverter, TcInMemory};
 
     impl From<mpsc::SendError<StoreAddr>> for EcssTmtcError {
         fn from(_: mpsc::SendError<StoreAddr>) -> Self {
@@ -999,7 +992,6 @@ pub mod std_mod {
         VerificationReporter: VerificationReportingProvider,
         RequestConverter: PusTcToRequestConverter<Request>,
         RequestRouter: PusRequestRouter<Request, Error = RoutingError>,
-        RoutingErrorHandler: PusRoutingErrorHandler<Error = RoutingError>,
         Request,
         RoutingError = GenericRoutingError,
     > {
@@ -1007,7 +999,7 @@ pub mod std_mod {
             PusServiceHelper<TcReceiver, TmSender, TcInMemConverter, VerificationReporter>,
         pub request_converter: RequestConverter,
         pub request_router: RequestRouter,
-        pub routing_error_handler: RoutingErrorHandler,
+        // pub routing_error_handler: RoutingErrorHandler,
         phantom: PhantomData<Request>,
     }
 
@@ -1018,7 +1010,7 @@ pub mod std_mod {
             VerificationReporter: VerificationReportingProvider,
             RequestConverter: PusTcToRequestConverter<Request, Error = PusPacketHandlingError>,
             RequestRouter: PusRequestRouter<Request, Error = RoutingError>,
-            RoutingErrorHandler: PusRoutingErrorHandler<Error = RoutingError>,
+            // RoutingErrorHandler: PusRoutingErrorHandler<Error = RoutingError>,
             Request,
             RoutingError: Clone,
         >
@@ -1029,7 +1021,7 @@ pub mod std_mod {
             VerificationReporter,
             RequestConverter,
             RequestRouter,
-            RoutingErrorHandler,
+            // RoutingErrorHandler,
             Request,
             RoutingError,
         >
@@ -1045,13 +1037,12 @@ pub mod std_mod {
             >,
             request_converter: RequestConverter,
             request_router: RequestRouter,
-            routing_error_handler: RoutingErrorHandler,
         ) -> Self {
             Self {
                 service_helper,
                 request_converter,
                 request_router,
-                routing_error_handler,
+                // routing_error_handler,
                 phantom: PhantomData,
             }
         }
@@ -1079,7 +1070,7 @@ pub mod std_mod {
                 self.request_router
                     .route(target_id, action_request, ecss_tc_and_token.token)
             {
-                self.routing_error_handler.handle_error(
+                self.request_router.handle_error(
                     target_id,
                     ecss_tc_and_token.token,
                     &tc,
@@ -1451,8 +1442,8 @@ pub mod tests {
     };
     use super::{
         EcssTcAndToken, EcssTcInSharedStoreConverter, EcssTcInVecConverter, GenericRoutingError,
-        MpscTcReceiver, PusPacketHandlerResult, PusPacketHandlingError, PusRoutingErrorHandler,
-        PusServiceHelper, TcInMemory, TmAsVecSenderWithId, TmAsVecSenderWithMpsc,
+        MpscTcReceiver, PusPacketHandlerResult, PusPacketHandlingError, PusServiceHelper,
+        TcInMemory, TmAsVecSenderWithId, TmAsVecSenderWithMpsc,
         TmInSharedPoolSenderWithBoundedMpsc, TmInSharedPoolSenderWithId,
     };
 
@@ -1766,44 +1757,9 @@ pub mod tests {
         }
     }
 
-    #[derive(Default)]
-    pub struct TestRoutingErrorHandler {
-        pub routing_errors: RefCell<VecDeque<(TargetId, GenericRoutingError)>>,
-    }
-
-    impl PusRoutingErrorHandler for TestRoutingErrorHandler {
-        type Error = GenericRoutingError;
-
-        fn handle_error(
-            &self,
-            target_id: TargetId,
-            _token: VerificationToken<TcStateAccepted>,
-            _tc: &PusTcReader,
-            error: Self::Error,
-            _time_stamp: &[u8],
-            _verif_reporter: &impl VerificationReportingProvider,
-        ) {
-            self.routing_errors
-                .borrow_mut()
-                .push_back((target_id, error));
-        }
-    }
-
-    impl TestRoutingErrorHandler {
-        pub fn is_empty(&self) -> bool {
-            self.routing_errors.borrow().is_empty()
-        }
-
-        pub fn retrieve_next_error(&mut self) -> (TargetId, GenericRoutingError) {
-            if self.routing_errors.borrow().is_empty() {
-                panic!("no routing request available");
-            }
-            self.routing_errors.borrow_mut().pop_front().unwrap()
-        }
-    }
-
     pub struct TestRouter<REQUEST> {
         pub routing_requests: RefCell<VecDeque<(TargetId, REQUEST)>>,
+        pub routing_errors: RefCell<VecDeque<(TargetId, GenericRoutingError)>>,
         pub injected_routing_failure: RefCell<Option<GenericRoutingError>>,
     }
 
@@ -1811,6 +1767,7 @@ pub mod tests {
         fn default() -> Self {
             Self {
                 routing_requests: Default::default(),
+                routing_errors: Default::default(),
                 injected_routing_failure: Default::default(),
             }
         }
@@ -1824,6 +1781,31 @@ pub mod tests {
             Ok(())
         }
 
+        pub fn handle_error(
+            &self,
+            target_id: TargetId,
+            _token: VerificationToken<TcStateAccepted>,
+            _tc: &PusTcReader,
+            error: GenericRoutingError,
+            _time_stamp: &[u8],
+            _verif_reporter: &impl VerificationReportingProvider,
+        ) {
+            self.routing_errors
+                .borrow_mut()
+                .push_back((target_id, error));
+        }
+
+        pub fn no_routing_errors(&self) -> bool {
+            self.routing_errors.borrow().is_empty()
+        }
+
+        pub fn retrieve_next_routing_error(&mut self) -> (TargetId, GenericRoutingError) {
+            if self.routing_errors.borrow().is_empty() {
+                panic!("no routing request available");
+            }
+            self.routing_errors.borrow_mut().pop_front().unwrap()
+        }
+
         pub fn inject_routing_error(&mut self, error: GenericRoutingError) {
             *self.injected_routing_failure.borrow_mut() = Some(error);
         }
diff --git a/satrs/src/pus/mode.rs b/satrs/src/pus/mode.rs
index 8d1f4ab..b5bbb85 100644
--- a/satrs/src/pus/mode.rs
+++ b/satrs/src/pus/mode.rs
@@ -2,7 +2,14 @@ use num_enum::{IntoPrimitive, TryFromPrimitive};
 #[cfg(feature = "serde")]
 use serde::{Deserialize, Serialize};
 
-use crate::{mode::ModeReply, request::GenericMessage};
+use crate::mode::ModeReply;
+
+#[cfg(feature = "alloc")]
+#[allow(unused_imports)]
+pub use alloc_mod::*;
+
+#[cfg(feature = "std")]
+pub use std_mod::*;
 
 pub const MODE_SERVICE_ID: u8 = 200;
 
@@ -19,8 +26,6 @@ pub enum Subservice {
     TmWrongModeReply = 8,
 }
 
-pub type GenericModeReplyPus = GenericMessage<ModeReply>;
-
 #[cfg(feature = "alloc")]
 #[cfg_attr(doc_cfg, doc(cfg(feature = "alloc")))]
 pub mod alloc_mod {}
@@ -33,11 +38,12 @@ pub mod std_mod {
     use satrs_shared::res_code::ResultU16;
     use spacepackets::{
         ecss::tm::{PusTmCreator, PusTmSecondaryHeader},
+        util::UnsignedEnum,
         SpHeader,
     };
 
     use crate::{
-        mode::{ModeReply, ModeRequest},
+        mode::{GenericModeReply, ModeRequest},
         pus::{
             mode::Subservice,
             verification::{
@@ -55,7 +61,7 @@ pub mod std_mod {
         fn can_not_reach_mode_result_code(&self) -> ResultU16;
     }
 
-    use super::{GenericModeReplyPus, MODE_SERVICE_ID};
+    use super::{ModeReply, MODE_SERVICE_ID};
 
     pub type PusModeServiceRequestHandler<
         TcReceiver,
@@ -64,7 +70,6 @@ pub mod std_mod {
         VerificationReporter,
         RequestConverter,
         RequestRouter,
-        RoutingErrorHandler,
         RoutingError = GenericRoutingError,
     > = PusTargetedRequestHandler<
         TcReceiver,
@@ -73,7 +78,6 @@ pub mod std_mod {
         VerificationReporter,
         RequestConverter,
         RequestRouter,
-        RoutingErrorHandler,
         ModeRequest,
         RoutingError,
     >;
@@ -124,7 +128,7 @@ pub mod std_mod {
         /// Main handler function to handle all received action replies.
         pub fn handle_mode_reply(
             &mut self,
-            mode_reply_with_id: &GenericModeReplyPus,
+            mode_reply_with_id: &GenericModeReply,
             time_stamp: &[u8],
         ) -> Result<(), EcssTmtcError> {
             let active_req = self.active_request_map.get(mode_reply_with_id.request_id);
@@ -135,6 +139,7 @@ pub mod std_mod {
             let active_req = active_req.unwrap().clone();
             let remove_entry = match mode_reply_with_id.message {
                 ModeReply::ModeReply(reply) => {
+                    reply.write_to_be_bytes(&mut self.tm_buf)?;
                     let req_id = verification::RequestId::from(mode_reply_with_id.request_id);
                     let mut sp_header = SpHeader::tm_unseg(
                         req_id.packet_id().apid(),
@@ -149,16 +154,15 @@ pub mod std_mod {
                         0,
                         Some(time_stamp),
                     );
-                    let pus_tm =
-                        PusTmCreator::new(&mut sp_header, sec_header, &mut self.tm_buf, true);
+                    let pus_tm = PusTmCreator::new(&mut sp_header, sec_header, &self.tm_buf, true);
                     self.tm_sender.send_tm(PusTmWrapper::Direct(pus_tm))?;
                     self.verification_reporter
                         .completion_success(active_req.token, time_stamp)
                         .map_err(|e| e.0)?;
                     true
                 }
-                ModeReply::CantReachMode(reached_mode) => {
-                    let fail_data_len = reached_mode.to_be_bytes(&mut self.tm_buf)?;
+                ModeReply::CantReachMode(reason) => {
+                    let fail_data_len = reason.write_to_be_bytes(&mut self.tm_buf)?;
                     self.verification_reporter
                         .completion_failure(
                             active_req.token,
@@ -172,9 +176,19 @@ pub mod std_mod {
                     true
                 }
                 ModeReply::WrongMode { expected, reached } => {
-                    // TODO: Generate completion failure with appropriate result code and reached
-                    // mode as context information.
-                    // self.verification_reporter.completion_success(active_req.token, time_stamp);
+                    let expected_len = expected.write_to_be_bytes(&mut self.tm_buf)?;
+                    let reached_len =
+                        reached.write_to_be_bytes(&mut self.tm_buf[expected_len..])?;
+                    self.verification_reporter
+                        .completion_failure(
+                            active_req.token,
+                            FailParams::new(
+                                time_stamp,
+                                &self.user_hook.can_not_reach_mode_result_code(),
+                                &self.tm_buf[0..expected_len + reached_len],
+                            ),
+                        )
+                        .map_err(|e| e.0)?;
                     true
                 }
                 _ => true,
@@ -187,3 +201,122 @@ pub mod std_mod {
         }
     }
 }
+
+#[cfg(test)]
+mod tests {
+
+    use std::sync::mpsc;
+
+    use crate::{
+        mode::{
+            ModeAndSubmode, ModeReplySender, ModeRequest, ModeRequestSender,
+            ModeRequestorAndHandlerMpsc, ModeRequestorMpsc,
+        },
+        pus::mode::ModeReply,
+        request::GenericMessage,
+    };
+
+    const TEST_CHANNEL_ID_0: u32 = 5;
+    const TEST_CHANNEL_ID_1: u32 = 6;
+    const TEST_CHANNEL_ID_2: u32 = 7;
+
+    #[test]
+    fn test_simple_mode_requestor() {
+        let (reply_sender, reply_receiver) = mpsc::channel();
+        let (request_sender, request_receiver) = mpsc::channel();
+        let mut mode_requestor = ModeRequestorMpsc::new(TEST_CHANNEL_ID_0, reply_receiver);
+        mode_requestor.add_message_target(TEST_CHANNEL_ID_1, request_sender);
+
+        // Send a request and verify it arrives at the receiver.
+        let request_id = 2;
+        let sent_request = ModeRequest::ReadMode;
+        mode_requestor
+            .send_mode_request(request_id, TEST_CHANNEL_ID_1, sent_request)
+            .expect("send failed");
+        let request = request_receiver.recv().expect("recv failed");
+        assert_eq!(request.request_id, 2);
+        assert_eq!(request.sender_id, TEST_CHANNEL_ID_0);
+        assert_eq!(request.message, sent_request);
+
+        // Send a reply and verify it arrives at the requestor.
+        let mode_reply = ModeReply::ModeReply(ModeAndSubmode::new(1, 5));
+        reply_sender
+            .send(GenericMessage::new(
+                request_id,
+                TEST_CHANNEL_ID_1,
+                mode_reply,
+            ))
+            .expect("send failed");
+        let reply = mode_requestor.try_recv_mode_reply().expect("recv failed");
+        assert!(reply.is_some());
+        let reply = reply.unwrap();
+        assert_eq!(reply.sender_id, TEST_CHANNEL_ID_1);
+        assert_eq!(reply.request_id, 2);
+        assert_eq!(reply.message, mode_reply);
+    }
+
+    #[test]
+    fn test_mode_requestor_and_request_handler_request_sending() {
+        let (_reply_sender_to_connector, reply_receiver_of_connector) = mpsc::channel();
+        let (_request_sender_to_connector, request_receiver_of_connector) = mpsc::channel();
+
+        let (request_sender_to_channel_1, request_receiver_channel_1) = mpsc::channel();
+        //let (reply_sender_to_channel_2, reply_receiver_channel_2) = mpsc::channel();
+        let mut mode_connector = ModeRequestorAndHandlerMpsc::new(
+            TEST_CHANNEL_ID_0,
+            request_receiver_of_connector,
+            reply_receiver_of_connector,
+        );
+        assert_eq!(
+            ModeRequestSender::local_channel_id(&mode_connector),
+            TEST_CHANNEL_ID_0
+        );
+        assert_eq!(
+            ModeReplySender::local_channel_id(&mode_connector),
+            TEST_CHANNEL_ID_0
+        );
+        assert_eq!(mode_connector.local_channel_id_generic(), TEST_CHANNEL_ID_0);
+
+        mode_connector.add_request_target(TEST_CHANNEL_ID_1, request_sender_to_channel_1);
+
+        // Send a request and verify it arrives at the receiver.
+        let request_id = 2;
+        let sent_request = ModeRequest::ReadMode;
+        mode_connector
+            .send_mode_request(request_id, TEST_CHANNEL_ID_1, sent_request)
+            .expect("send failed");
+
+        let request = request_receiver_channel_1.recv().expect("recv failed");
+        assert_eq!(request.request_id, 2);
+        assert_eq!(request.sender_id, TEST_CHANNEL_ID_0);
+        assert_eq!(request.message, ModeRequest::ReadMode);
+    }
+
+    #[test]
+    fn test_mode_requestor_and_request_handler_reply_sending() {
+        let (_reply_sender_to_connector, reply_receiver_of_connector) = mpsc::channel();
+        let (_request_sender_to_connector, request_receiver_of_connector) = mpsc::channel();
+
+        let (reply_sender_to_channel_2, reply_receiver_channel_2) = mpsc::channel();
+        let mut mode_connector = ModeRequestorAndHandlerMpsc::new(
+            TEST_CHANNEL_ID_0,
+            request_receiver_of_connector,
+            reply_receiver_of_connector,
+        );
+        mode_connector.add_reply_target(TEST_CHANNEL_ID_2, reply_sender_to_channel_2);
+
+        // Send a request and verify it arrives at the receiver.
+        let request_id = 2;
+        let sent_reply = ModeReply::ModeInfo(ModeAndSubmode::new(3, 5));
+        mode_connector
+            .send_mode_reply(request_id, TEST_CHANNEL_ID_2, sent_reply)
+            .expect("send failed");
+        let reply = reply_receiver_channel_2.recv().expect("recv failed");
+        assert_eq!(reply.request_id, 2);
+        assert_eq!(reply.sender_id, TEST_CHANNEL_ID_0);
+        assert_eq!(reply.message, sent_reply);
+    }
+
+    #[test]
+    fn test_mode_reply_handler() {}
+}